Disclaimer: The purpose of the Open Case Studies project is to demonstrate the use of various data science methods, tools, and software in the context of messy, real-world data. A given case study does not cover all aspects of the research process, is not claiming to be the most appropriate way to analyze a given data set, and should not be used in the context of making policy decisions without external consultation from scientific experts.

This work is licensed under the Creative Commons Attribution-NonCommercial 3.0 (CC BY-NC 3.0) United States License.

To cite this case study please use:

Wright, Carrie, and Ontiveros, Michael and Jager, Leah and Taub, Margaret and Hicks, Stephanie. (2020). https://github.com/opencasestudies/ocs-youth-mental-health-case-study. Mental Health of American Youth (Version v1.0.0).

Motivation


Rates of depression appear to have been increasing among American youths since around 2010 according to a recent report. A recent study) also shows that youths appear to be seeking more care from mental health services.

This case study will explore how rates of major depressive episodes have changed since the early 2000s. As well as how rates of treatment for depression of youths have changed over time.

Photo by K. Mitch Hodge on Unsplash

The major symptoms of a major depressive episode include:

Sleep disorder (increased or decreased)
Interest deficit (anhedonia)
Guilt (worthlessness, hopelessness, regret)
Energy deficit
Concentration deficit
Appetite disorder (increased or decreased)
Psychomotor retardation or agitation
Suicidality

[source]

Click here to see the diagnostic requirements for a major depressive episode according to the DSM 5

Five or more of the following symptoms have been present and documented during the same two-week period and represent a change from previous functioning; at least one of the symptoms is either (1) depressed mood or (2) loss of interest or pleasure.

Note: Do not include symptoms that are clearly attributable to another medical condition.

  1. Depressed mood most of the day, nearly every day, as indicated by either subjective report (e.g., feels sad, empty, hopeless) or observation made by others (e.g., appears tearful)

  2. Markedly diminished interest or pleasure in all, or almost all, activities most of the day, nearly every day (as indicated by either subjective account or observation)

  3. Significant weight loss when not dieting or weight gain (e.g., a change of more than 5% of body weight in a month), or decrease or increase in appetite nearly every day

  4. Insomnia or hypersomnia nearly every day

  5. Psychomotor agitation or retardation nearly every day (observable by others, not merely subjective feelings of restlessness or being slowed down)

  6. Fatigue or loss of energy nearly every day

  7. Feelings of worthlessness or excessive or inappropriate guilt (which may be delusional) nearly every day (not merely self-reproach or guilt about being sick)

  8. Diminished ability to think or concentrate, or indecisiveness, nearly every day (either by subjective account or as observed by others)

  9. Recurrent thoughts of death (not just fear of dying), recurrent suicidal ideation without a specific plan, or a suicide attempt or a specific plan for committing suicide

B. The symptoms do not meet criteria for a mixed episode.

C. The episode is not attributable to the physiological effects of a substance or to another medical condition.

Note: Criteria A-C represent a major depressive episode.

Note: Responses to a significant loss (e.g., bereavement, financial ruin, losses from a natural disaster, a serious medical illness or disability) may include feelings of intense sadness, rumination about the loss, insomnia, poor appetite and weight loss noted in Criterion A, which may resemble a depressive episode. Although such symptoms may be understandable or considered appropriate to the loss, the presence of a major depressive episode in addition to the normal response to a significant loss should also be carefully considered. This decision inevitably requires the exercise of clinical judgment based on the individual’s history of and the cultural norms for the expression of distress in the context of loss.

D. The occurrence of the major depressive episode is not better explained by schizoaffective disorder, schizophrenia, schizophreniform disorder, delusional disorder, or other specified and unspecified schizophrenia spectrum and other psychotic disorders.

E. There has never been a manic episode or a hypomanic episode.

Note: This exclusion does not apply if all of the manic-like or hypomanic-like episodes are substance-induced or are attributable to the physiological effects of another medical condition.

This case study is motivated by the following two articles:

Twenge JM, Cooper AB, Joiner TE, Duffy ME, Binau SG. Age, period, and cohort trends in mood disorder indicators and suicide-related outcomes in a nationally representative dataset, 2005-2017. J Abnorm Psychol.128,3 (2019):185-199. doi:10.1037/abn0000410

Olfson, M., Blanco, C., Wang, S., Laje, G. & Correll, C. U. National Trends in the Mental Health Care of Children, Adolescents, and Adults by Office-Based Physicians. JAMA Psychiatry. 71, 81 (2014):81-90. doi: 10.1001/jamapsychiatry.2013.3074.

The main findings of the first article are:

Rates of major depressive episode in the last year increased 52% 2005–2017 (from 8.7% to 13.2%) among adolescents aged 12 to 17 and 63% 2009–2017 (from 8.1% to 13.2%) among young adults 18–25.

Serious psychological distress in the last month and suicide-related outcomes (suicidal ideation, plans, attempts, and deaths by suicide) in the last year also increased among young adults 18–25 from 2008–2017 (with a 71% increase in serious psychological distress), with less consistent and weaker increases among adults ages 26 and over.

Cultural trends contributing to an increase in mood disorders and suicidal thoughts and behaviors since the mid-2000s, including the rise of electronic communication and digital media and declines in sleep duration, may have had a larger impact on younger people, creating a cohort effect.

While the main findings of the second article are:

Compared with adult mental health care, the mental health care of young people has increased more rapidly.

Between 1995-1998 and 2007-2010, visits resulting in mental disorder diagnoses per 100 population increased significantly faster for youths (from 7.78 to 15.30 visits) than for adults (from 23.23 to 28.48 visits) (interaction: P < .001).

Psychiatrist visits also increased significantly faster for youths (from 2.86 to 5.71 visits).

Again while depression appear to be on the rise for youths, youths also appear to be seeking more mental health care.

In this case study we will be using data from the National Survey on Drug Use and Health (NSDUH) related to treatment and major depressive episode rate to explore how this have changed over time and how different groups compare. This data was also used in the first referenced article.

Main Questions


Our main questions:

  1. How have depression rates in American youth changed since 2004, according to the NSDUH data? How have rates differed between different youth subgroups (age, gender, ethnicity)?
  2. Do mental health services appear to be reaching more youths? Again, how have rates differed between different youth subgroups (age, gender, ethnicity)?

Learning Objectives


Statistical Learning Objectives:

  1. Define and create a contingency table.
  2. Implementation of a chi-squared test for independence.
  3. Interpretation of a chi-squared test for independence.

Data science Learning Objectives:

  1. Scrape data directly from a website (rvest).
  2. Subset and filter data (dplyr).
  3. Write functions to wrangle data repetitively.
  4. Work with character strings (stringr).
  5. Reshape data into different formats (tidyr).
  6. Data visualizations (ggplot2) with labels (directlabels) and facets for different groups.

In this case study, we will especially focus on using packages and functions from the Tidyverse, such as rvest. The tidyverse is a library of packages created by RStudio. While some students may be familiar with previous R programming packages, these packages make data science in R especially efficient.


We will begin by loading the packages that we will need:

Package Use
here to easily load and save data
rvest to scrape web pages
dplyr to scrape web pages
magrittr to scrape web pages
stringr to manipulate strings
tidyr to change the shape or format of tibbles to wide and long
tibble to create tibbles and convert values of a column to row names
ggplot2 to create plots
directlabels to add labels directly to lines in plots
forcats to reorder factor for plot
cowplot to combine plots together

The first time we use a function, we will use the :: to indicate which package we are using. Unless we have overlapping function names, this is not necessary, but we will include it here to be informative about where the functions we will use come from.

Context


According to the CDC the rate of suicide has also increased for most age groups in the United States over the past decade and a half.

[source]

While suicide does appear to be increasing among youths it also appears to be increasing among middle aged adults for both females and males.

[source]

According to the CDC:

Since 2008, suicide has ranked as the 10th leading cause of death for all ages in the United States. In 2016, suicide became the second leading cause of death among those aged 10–34 and the fourth leading cause among those aged 35–54.

[source]

So although suicide is on the rise for most age groups, suicide is one of the top two contributors to death for youths.

Thus this warrants further examination of the mental health of American youths.

[source]

Historically, suicide rates were much higher before 1950, however, we are seeing an increase in the last 20 years.

[source]

Besides the US, other countries are also experiencing increased rates of depression in youths. See this report from the World Health Organization about rates of depression in other countries.

See here for an interesting discussion about what may be causing increased depression rates.

According to the National Institute of Mental Health (NIMH):

If you are in crisis and need help, call this toll-free number for the National Suicide Prevention Lifeline (NSPL), available 24 hours a day, every day: 1-800-273-TALK (8255). The service is available to everyone. The deaf and hard of hearing can contact the Lifeline via TTY at 1-800-799-4889. All calls are confidential. You can also visit the Lifeline’s website at www.suicidepreventionlifeline.org.

The Crisis Text Line is another free, confidential resource available 24 hours a day, seven days a week. Text “HOME” to 741741 and a trained crisis counselor will respond to you with support and information over text message. Visit www.crisistextline.org.

Also see here for more information about how to recognize and help youths experiencing symptoms of depression.

Limitations


avocado -Michael:Perhaps “underestimates in the p-values…” is not the correct way to phrase this. I would look for a better way to word this.-Carrie:This is my attempt after Michael’s… open to changes!

There are some important considerations regarding this data analysis to keep in mind:

  1. The data that we will use come from a survey and are therefore values from a sample that estimate that of the true population. In our statistical analysis we use these sample values as if they are population estimates (because this is all we have access to). Thus our results are not necessarily indicative of true differences.

  2. Furthermore, the sampling mechanism utilized can introduce selection bias in cases where the the sampling methods do not produce a representative sample.

  3. Data is collected from human participants; this presents the potential for information bias, as there is the potential that participants in the sampling frame may for a variety of reasons report inaccurate information.

What are the data?


We will be using data from the National Survey on Drug Use and Health (NSDUH) which is directed by the Substance Abuse and Mental Health Services Administration (SAMHSA), an agency in the U.S. Department of Health and Human Services (DHHS).

This survey started in 1971 and is conducted annually in all 50 states and the District of Columbia. Approximately 70,000 people (age 12 and up) are interviewed each year about health related issues. Only civilian, non-institutionalized individuals are included. Households are randomly selected and than a professional interviewer visits the addresses and asks one or two of the residents to interview. The interviewer brings a laptop with them that the participants use to fill out the survey which typically takes an hour to complete. If a participant chooses to participate they receive $30 in cash. All collected information is confidential and is used for disease surveillance and to guide public policy particularly focused on drug and alcohol use as well as mental health. See here for more details about the survey.

This data is made available publicly online on the Substance Abuse & Mental Health Data Archive.

At the website for the survey data, you can see that the results are displayed in many tables. Importantly, there is no obvious way to download the data directly from this particular website.

If one clicks on the TOC button on the far right upper corner they will be directed to another website, where a large pdf document containing of all of the results can be downloaded.

We are interested in investigating how depression rates have changed and how youths are interacting with mental health services. Thus the following tables are of interest to us are:

Table Details
Table 11.1A Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Numbers in Thousands, 2002-2018
Table 11.1B Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Percentages, 2002-2018
Table 11.2A Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2004-2018
Table 11.2B Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2004-2018
Table 11.3A Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2006-2018
Table 11.3B Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2006-2018
Table 11.4A Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Numbers in Thousands, 2004-2018
Table 11.4B Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Percentages, 2004-2018

According to the NSDUH 2018 report

Respondents were defined as having had an MDE in the past 12 months if they had at least one period of 2 weeks or longer in the past year when they experienced a depressed mood or loss of interest or pleasure in daily activities, accompanied by problems with sleeping, eating, energy, concentration, or self-worth. The MDE questions are based on diagnostic criteria from DSM-5. Some of the wordings of the depression questions for adolescents aged 12 to 17 and adults aged 18 or older differed slightly to make the questions more developmentally appropriate for adolescents.

Adolescents were defined as having an MDE with severe impairment if their depression caused severe problems with their ability to do chores at home, do well at work or school, get along with their family, or have a social life.

Data Import


Data is often made available online. Usually, the data we are interested in is made available for download on the page as a delimited text file or an excel file. However, sometimes data is not made available in this manner, such as the NSDUH survey data.

How do we proceed in this scenario?

We can manually copy each cell of data, however, this process is often inefficient, subject to error, and not reproducible. Say we wanted to run an analysis next year on the next years data and it happens to be formatted in the same way.

We can also use R for web scraping.

Web scraping is the process of extracting data from a website.

Basic steps of web scraping

There are two main steps to web scraping:

  1. Identify location of data on the webpage that will be scraped

  2. Save the webpage element to an object

We accomplish STEP 1 with our web browser.

We accomplish STEP 2 in the R programming environment.

Additional resources for web scraping:

In this case study we will scrape data from the tables on the NSDUH survey website. This data is available in a large PDF with all the results form the year. However it is not easy to find this PDF and it would be difficult and time consuming to find our tables of interest and to extract the data from the pdf with pdftools. Again, if we instead decided to copy paste the data from the website to another file that we would also need to import, this would not be as efficient or reproducible and might result in errors.

Alternatively, we will use the rvest package to scrape the data directly from the tables on the website. Assuming the data next year would be displayed in a similar manner, this could allow us simply modify our code based on the url for the data next year to run the same analysis on the data easily.

The rvest package can be thought of as the pdftools package for web scraping. Upon pulling the data, additional wrangling will likely be required; but like the pdftools package, rvest streamlines the extraction process.

Steps for scraping tables

The two web scraping steps for these tables can be broken down even further:

  1. Identify location of data that will be scraped
  • right-click to inspect element (webpage)
  • hover pointer over components of element (webpage) until the data has been found
  • copy XPath of data sought
  1. Save webpage element to an object in R
  • import html code for the webpage
  • extract pieces of HTML documents (webpage) using XPath
  • parse the extracted data into a data frame

Below is a animated overview of the process.


Now let’s go through each step together:

1) Identify location of data that will be scraped

First, let’s go to the web page with all the tables we are interested in scraping

Once on the webpage, there aren’t any visible options to download the data.

Right-click and select “Inspect”

A window opens.

This window allows us to glance at the internal mechanics of the webpage. To scrape the data from the webpage, we need to first learn a little bit about the components that make it the web page it is.

Hovering our mouse over the elements of the webpage highlights the respective section of the webpage it represents. By hovering over several elements—and clicking on the elements on the right side of the screen—we can identify the element that contains the data we are looking for. Another option for identifying XPaths is to use the selectorgadget tool.

Right click on the element and copy the XPath. We will need this XPath for the next step.

Now we can return to the R programming environment.


2) Save webpage element to an object in R

For the first table we want to scrape, the XPath is /html/body/div[4]/div[1]/table. We use this XPath with functions from the rvest package to scrape the data from this table.

Let’s explore this step in greater detail:

We need to:

  • import html code for the webpage
  • extract pieces (table) out of HTML documents (webpage) using XPath
  • parse the html table into a data frame

To do this:

  • We import the html code using the read_html() function of the rvest package
  • We extract specific components of the webpage using the html_nodes() function of the rvest package
  • We convert this html table into a dataframe using the html_table()function of the rvest package

The rvest package provides wrappers for the xml2 and httr packages, thus we can just install and load the rvest package and it will install and load dependency packages like xml2 and httr and allow us to use functions from both of these packages.

In fact, when we load rvest the first time we see:

In this case, we are scraping table 11.1a from the website. First we assign the url to a character string to use within the read_html() function of the xml2 package.

One could also directly use the url but this is less convenient for piping.

Click here if you are unfamiliar with piping in R, which uses this %>% operator

By piping we mean using the %>% pipe operator which are usable when loading the tidyverse or several of the packages within the tidyverse like dplyr because they load the magrittr package. This allows us to perform multiple sequential steps on one data input.

The read_html() function then allows us to save the html document for the webpage inside R.

{html_document}
<html lang="en">
[1] <head>\n<!-- Google Tag Manager --><script>(function(w,d,s,l,i){w[l]=w[l] ...
[2] <body>\r\n<!-- Google Tag Manager (noscript) -->\r\n<noscript><iframe src ...

Then we use the html_nodes() function of the rvest package to select just the table11.1a element of the webpage.

See this tutorial (and the answers in case you get stuck) on CSS selectors to understand more about how this function works to use the xpath to select the elements of interest from the webpage.

{xml_nodeset (1)}
[1] <table class="rti">\n<caption>Table 11.1A – Settings Where Mental Health  ...

Finally, the html_table() function of the rvest package parses the html object into a data frame.

[[1]]
     Setting Where Mental Health ServiceWas Received 2002 2003 2004 2005 2006
     2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018
 [ reached 'max' / getOption("max.print") -- omitted 21 rows ]
List of 1
 $ :'data.frame':   21 obs. of  18 variables:
  ..$ Setting Where Mental Health ServiceWas Received: chr [1:21] "SPECIALTY MENTAL HEALTH SERVICE1" "Outpatient" "Private Therapist, Psychologist,\r\n   Psychiatrist, Social Worker, or\r\n   Counselor" "Mental Health Clinic or Center" ...
  ..$ 2002                                           : chr [1:21] "2,898a" "2,662a" "2,254a" "611a" ...
  ..$ 2003                                           : chr [1:21] "3,065a" "2,795a" "2,347a" "635a" ...
  ..$ 2004                                           : chr [1:21] "3,348a" "3,015a" "2,523a" "716a" ...
  ..$ 2005                                           : chr [1:21] "3,362a" "3,048a" "2,573a" "657a" ...
  ..$ 2006                                           : chr [1:21] "3,255a" "2,931a" "2,416a" "587a" ...
  ..$ 2007                                           : chr [1:21] "3,104a" "2,787a" "2,365a" "583a" ...
  ..$ 2008                                           : chr [1:21] "3,129a" "2,837a" "2,408a" "567a" ...
  ..$ 2009                                           : chr [1:21] "2,925a" "2,650a" "2,296a" "537a" ...
  ..$ 2010                                           : chr [1:21] "2,920a" "2,635a" "2,265a" "547a" ...
  ..$ 2011                                           : chr [1:21] "3,101a" "2,842a" "2,409a" "547a" ...
  ..$ 2012                                           : chr [1:21] "3,118a" "2,846a" "2,427a" "610a" ...
  ..$ 2013                                           : chr [1:21] "3,341a" "3,064a" "2,572a" "731a" ...
  ..$ 2014                                           : chr [1:21] "3,369a" "3,110a" "2,698a" "760a" ...
  ..$ 2015                                           : chr [1:21] "3,253a" "2,958a" "2,532a" "792a" ...
  ..$ 2016                                           : chr [1:21] "3,598a" "3,239a" "2,819a" "929" ...
  ..$ 2017                                           : chr [1:21] "3,646a" "3,328" "2,908" "995" ...
  ..$ 2018                                           : chr [1:21] "3,901" "3,547" "3,080" "977" ...

We can see that the output is a list with one element, to extract the data from the list we will use brackets [[]] to select the first element of the list.

Putting this all of this together we can do the entire process like this with our pipe operator %>%.

Now need to repeat the above process for the other tables we are interested in.

Writing a function to scrape multiple tables

We can create a function to accomplish this succinctly. Functions allow us to perform the same process on multiple data inputs. See this other case study for more details about how to write a function.

In general, the process pf writing functions involves first specifying an input that is used within the function to create an output. In this case the data input is XPATH which will be replaced by an actual XPath and then used in the subsequent steps to scrape the data from each table that an XPath is supplied for.

We will all this function scraper.

Now we can apply the function we created to each of the XPaths for each of the tables on the website that we would like to use in our data analysis.

Great! We have successfully scraped the data.

Now we need to wrangle the data.

Data Exploration and Wrangling


Now that we’ve imported the data, let’s see if we can wrangle a table. Since the data appears to be formatted in a similar way in each of the tables, it is likely that whatever steps we take to wrangle this first table will also be necessary in the wrangling of subsequent tables. This is because well-maintained data sources often format different datasets similarly. We can take advantage of this similarity to speed up the wrangling process.

Table11.1a

First we want to remove the last row of our data frame, which happens to be the legend of our table. Recall from looking at the website that there is a legend for this table.

We can take a look at the last row using the tail function of the dplyr package. We can specify that we only want to see the last row by using the n = 1 argument.

# A tibble: 1 x 18
  `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
  <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "* = low precis… "* = … "* = … "* = … "* = … "* = … "* = … "* = … "* = …
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

We can see that the legend is repeated for every column. Let’s take a look at the year 2004 column.

# A tibble: 1 x 1
  `2004`                                                                        
  <chr>                                                                         
1 "* = low precision; -- = not available; da = does not apply; nc = not compara…

Let’s save this so that we can refer back to it later:

Another way to look at the last row is to use the n() function of the dplyr package. This function can be used inside other dplyr functions and it counts the total number of observations of a group. Within the slice() function of the dplyr package, it allows you to refer the full length of the object.

# A tibble: 1 x 18
  `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
  <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "* = low precis… "* = … "* = … "* = … "* = … "* = … "* = … "* = … "* = …
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

We can use the slice() function of the dplyr package to remove this row, by using the slicefunction to select from the first row using 1: to the second to last row using n()-1.

We are also going to use a special pipe operator from the magrittr package called the compound assignment pipe-operator or sometimes the double pipe operator. This allows us to use the table11.1a as our input and reassign it at the end after all the steps have been performed.

We will also first change the data to be a tibble.), which is the tidyverse version of a data frame using the as_tibble() function of the dplyr package and the tibble package.

Now let’s take a look at data:

# A tibble: 20 x 18
   `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
   <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 "SPECIALTY MENT… "2,89… "3,06… "3,34… "3,36… "3,25… "3,10… "3,12… "2,92…
 2 "Outpatient"     "2,66… "2,79… "3,01… "3,04… "2,93… "2,78… "2,83… "2,65…
 3 "Private Therap… "2,25… "2,34… "2,52… "2,57… "2,41… "2,36… "2,40… "2,29…
 4 "Mental Health … "611a" "635a" "716a" "657a" "587a" "583a" "567a" "537a"
 5 "Partial Day Ho… "440"  "425"  "439"  "449"  "471"  "416"  "374a" "340a"
 6 "In-Home Therap… "693a" "656a" "762a" "731a" "719a" "707a" "716a" "657a"
 7 "Inpatient or R… "509a" "542a" "629"  "619"  "596"  "581a" "539a" "524a"
 8 "Hospital"       "422a" "467a" "515"  "529"  "516"  "511a" "469a" "440a"
 9 "Residential Tr… "224a" "233a" "299"  "229a" "225a" "199a" "198a" "213a"
10 "NONSPECIALTY M… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "3,43…
11 "Education2,3"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "2,93…
12 "School Social … "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "2,28…
13 "Special School… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "975a"
14 "General Medici… ""     ""     ""     ""     ""     ""     ""     ""    
15 "Pediatrician o… "657a" "732"  "840"  "810"  "694"  "692"  "710"  "605a"
16 "Juvenile Justi… ""     ""     ""     ""     ""     ""     ""     ""    
17 "Juvenile Deten… "--"   "--"   "--"   "--"   "--"   "--"   "--"   "109a"
18 "Child Welfare"  ""     ""     ""     ""     ""     ""     ""     ""    
19 "Foster Care or… "157a" "179a" "158a" "143a" "129"  "114"  "118"  "92"  
20 "SPECIALTY MENT… "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "nc"   "1,22…
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

Great! We can see the the legend is no longer part of the data.

Now let’s use the legend to recode the data. There are many different values for missing data, that we would like to replace with NA instead. We can use the pull() function of the dplyr package to take a look at the legend data:

[1] "* = low precision; -- = not available; da = does not apply; nc = not comparable due to methodological changes; nr = not reported due to measurement issues.\r\nNOTE: Some 2006 to 2010 estimates may differ from previously published estimates due to updates (see Section 3.3.5 in Chapter 3 of the 2018 National Survey on Drug Use and Health: Methodological Summary and Definitions).\r\nNOTE: Mental health services for persons aged 12 to 17 includes treatment/counseling for emotional or behavioral problems not caused by drug or alcohol use. Respondents with unknown mental health service information were excluded.\r\nNOTE: Respondents could indicate multiple service settings; thus, the response categories are not mutually exclusive.a The difference between this estimate and the 2018 estimate is statistically significant at the .05 level. Rounding may make the estimates appear identical.1 Because of revisions in 2013 to Specialty Mental Health Service estimates, these 2002 to 2012 estimates may differ from estimates published prior to the 2013 NSDUH.2 Because of revisions in 2009 to the questions on the Source of Youth Mental Health Education Services, these estimates are not comparable with the education services estimates published prior to the 2009 NSDUH.3 Respondents who did not report their school enrollment status, who reported not being enrolled in school in the past 12 months, or who reported being home-schooled were not asked about receipt of mental health services from this setting; however, respondents who reported not being enrolled in school in the past 12 months were classified as not having received treatment/counseling from this setting.\r\nDefinitions: Measures and terms are defined in Appendix A.\r\nSource: SAMHSA, Center for Behavioral Health Statistics and Quality, National Survey on Drug Use and Health, 2002-2018."

Looks like we want to replace values that are: *, --, da, nc, and nr. We can use the na_if() function to recode these values to NA.

avocado… there isn’t support for doing this in one command… but could at least do two commands

# A tibble: 20 x 18
   `Setting Where … `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009`
   <chr>            <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 "SPECIALTY MENT… 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a
 2 "Outpatient"     2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a
 3 "Private Therap… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a
 4 "Mental Health … 611a   635a   716a   657a   587a   583a   567a   537a  
 5 "Partial Day Ho… 440    425    439    449    471    416    374a   340a  
 6 "In-Home Therap… 693a   656a   762a   731a   719a   707a   716a   657a  
 7 "Inpatient or R… 509a   542a   629    619    596    581a   539a   524a  
 8 "Hospital"       422a   467a   515    529    516    511a   469a   440a  
 9 "Residential Tr… 224a   233a   299    229a   225a   199a   198a   213a  
10 "NONSPECIALTY M… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3,430a
11 "Education2,3"   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,931a
12 "School Social … <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,286 
13 "Special School… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975a  
14 "General Medici… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 "Pediatrician o… 657a   732    840    810    694    692    710    605a  
16 "Juvenile Justi… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 "Juvenile Deten… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109a  
18 "Child Welfare"  <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 "Foster Care or… 157a   179a   158a   143a   129    114    118    92    
20 "SPECIALTY MENT… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1,226a
# … with 9 more variables: `2010` <chr>, `2011` <chr>, `2012` <chr>,
#   `2013` <chr>, `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>,
#   `2018` <chr>

Now let’s rename the first column using the rename() function of the dplyr package. This requires listing the new name first like so: new_name = old_name.

# A tibble: 6 x 18
  MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
  <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
1 "SPECIALTY… 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a 2,920a
2 "Outpatien… 2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a 2,635a
3 "Private T… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a 2,265a
4 "Mental He… 611a   635a   716a   657a   587a   583a   567a   537a   547a  
5 "Partial D… 440    425    439    449    471    416    374a   340a   362a  
6 "In-Home T… 693a   656a   762a   731a   719a   707a   716a   657a   674a  
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Nice!

Now you may notice that the individual values have an "a" after the numeric value.

According to the legend this indicates if “the difference between this estimate and the 2018 estimate is significant at the .05 level.”

While this is useful information, it makes it difficult to work with our numeric values, so we want to remove them.

Since lower case “a” values occur in the first column values, we want to makes sure we don’t remove these.

So how can we do this? We can use the stringr package to modify character strings. and we can use the dplyr functions mutate(), select() and across() to specify want columns we want to change.

Currently all of our data is of class character as indicated by the <chr> under the column names.

Click here for an explanation of what a character string is

There are several classes of data in R programming. Character is one of these classes. A character string is an individual data value made up of characters. This can be a paragraph, like the legend for the table, or it can be a single letter or number like the letter "a" or the number "3". If data is of class character, than the numeric values will not be processed like a numeric value in a mathematical sense. If you want your numeric values to be interpreted that way, they need to be converted to a numeric class. The options typically used are integer (which has no decimal place) and double precision (which has a decimal place).

The stringr package has functions that allow us to replace (the str_replace() function) or remove(the str_remove() function) characters.

To use these we need to be able to specify what we want to remove and replace.

Here is a part of a cheatsheet about string manipulation from RStudio.

We can see that we can refer to any digit (such as 1,2,3 etc.) as [:digit:]. We can also see that we can refer to any punctuation mark as [:punct:]. Finally, we see that spaces and tabs can be referred to as [:blank:].

If we take a closer look at the first column of our table (using the pull() function of the dplyr package), we can see that besides the "a" values that we see adjacent to our numeric values in the body of the table, we also some large white spaces, some numeric values, instances of \r\n, as well as some commas and other punctuation marks.

 [1] "SPECIALTY MENTAL HEALTH SERVICE1"                                                                                
 [2] "Outpatient"                                                                                                      
 [3] "Private Therapist, Psychologist,\r\n   Psychiatrist, Social Worker, or\r\n   Counselor"                          
 [4] "Mental Health Clinic or Center"                                                                                  
 [5] "Partial Day Hospital or Day Treatment\r\n   Program"                                                             
 [6] "In-Home Therapist, Counselor, or Family\r\n   Preservation Worker"                                               
 [7] "Inpatient or Residential1"                                                                                       
 [8] "Hospital"                                                                                                        
 [9] "Residential Treatment Center"                                                                                    
[10] "NONSPECIALTY MENTAL HEALTH\r\nSERVICE2"                                                                          
[11] "Education2,3"                                                                                                    
[12] "School Social Worker, School Psychologist,\r\n   or School Counselor"                                            
[13] "Special School or Program within a Regular\r\n   School for Students with Emotional or\r\n   Behavioral Problems"
[14] "General Medicine"                                                                                                
[15] "Pediatrician or Other Family Doctor"                                                                             
[16] "Juvenile Justice"                                                                                                
[17] "Juvenile Detention Center, Prison, or Jail"                                                                      
[18] "Child Welfare"                                                                                                   
[19] "Foster Care or Therapeutic Foster Care"                                                                          
[20] "SPECIALTY MENTAL HEALTH SERVICES\r\nAND EDUCATION, GENERAL MEDICINE\r\nOR CHILD WELFARE SERVICES1,2,3"           

We can use the str_remove_all() function which is a variant of the str_remove() function of the stringr package (which allows us to remove all occurrences of specified characters in each row rather than just the first occurrence, which is what str_remove() does), to remove the digit values, the \r\n characters and the punctuation marks from the column called MHS_setting.

Using the mutate() function we specify that we want to change this particular column and replace it with a version of this column that has removed characters that match digits, r\n or punctuation marks.

We need to specify that the character strings that should be used can be found in the MHS_setting column by using the string = argument and the patterns to find and remove are specified using the pattern = argument.

To allow us to look for all three of these patterns at the same time, we can use the | symbol between each pattern.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 SPECIALTY … 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a 2,920a
 2 Outpatient  2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a 2,635a
 3 Private Th… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a 2,265a
 4 Mental Hea… 611a   635a   716a   657a   587a   583a   567a   537a   547a  
 5 Partial Da… 440    425    439    449    471    416    374a   340a   362a  
 6 InHome The… 693a   656a   762a   731a   719a   707a   716a   657a   674a  
 7 Inpatient … 509a   542a   629    619    596    581a   539a   524a   531a  
 8 Hospital    422a   467a   515    529    516    511a   469a   440a   447a  
 9 Residentia… 224a   233a   299    229a   225a   199a   198a   213a   217a  
10 NONSPECIAL… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3,430a 3,465a
11 Education   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,931a 2,957a
12 School Soc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,286  2,214 
13 Special Sc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975a   1,054a
14 General Me… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 Pediatrici… 657a   732    840    810    694    692    710    605a   601a  
16 Juvenile J… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 Juvenile D… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109a   80a   
18 Child Welf… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 Foster Car… 157a   179a   158a   143a   129    114    118    92     108   
20 SPECIALTY … <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1,226a 1,283a
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

We also want to replace the spaces with a single space. We can see that sometimes there appears to be more than one space. We can specify that we want any occurrence of 1 or more to be replaced by using the {1,} notation.

See here for an explanation of this on the cheat sheet:

So now we will use the str_replace_all() function of the stringr package. In this case we also need to specify a replacement with the replacement = argument.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 SPECIALTY … 2,898a 3,065a 3,348a 3,362a 3,255a 3,104a 3,129a 2,925a 2,920a
 2 Outpatient  2,662a 2,795a 3,015a 3,048a 2,931a 2,787a 2,837a 2,650a 2,635a
 3 Private Th… 2,254a 2,347a 2,523a 2,573a 2,416a 2,365a 2,408a 2,296a 2,265a
 4 Mental Hea… 611a   635a   716a   657a   587a   583a   567a   537a   547a  
 5 Partial Da… 440    425    439    449    471    416    374a   340a   362a  
 6 InHome The… 693a   656a   762a   731a   719a   707a   716a   657a   674a  
 7 Inpatient … 509a   542a   629    619    596    581a   539a   524a   531a  
 8 Hospital    422a   467a   515    529    516    511a   469a   440a   447a  
 9 Residentia… 224a   233a   299    229a   225a   199a   198a   213a   217a  
10 NONSPECIAL… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3,430a 3,465a
11 Education   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,931a 2,957a
12 School Soc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2,286  2,214 
13 Special Sc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975a   1,054a
14 General Me… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 Pediatrici… 657a   732    840    810    694    692    710    605a   601a  
16 Juvenile J… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 Juvenile D… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109a   80a   
18 Child Welf… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 Foster Car… 157a   179a   158a   143a   129    114    118    92     108   
20 SPECIALTY … <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1,226a 1,283a
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Now to finally remove the “a” values and the commas from the body of the table we can use str_remove_all() function yet again. However this time to specify that we want all columns except the first column called MHS_setting, we can use the across() function of the dplyr package. This allows us to specify what columns we want to mutate by using the .cols = argument. We can select all columns except the first column called MHS_setting by using a minus sign - in front of the column name.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>       <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr>  <chr> 
 1 SPECIALTY … 2898   3065   3348   3362   3255   3104   3129   2925   2920  
 2 Outpatient  2662   2795   3015   3048   2931   2787   2837   2650   2635  
 3 Private Th… 2254   2347   2523   2573   2416   2365   2408   2296   2265  
 4 Mental Hea… 611    635    716    657    587    583    567    537    547   
 5 Partial Da… 440    425    439    449    471    416    374    340    362   
 6 InHome The… 693    656    762    731    719    707    716    657    674   
 7 Inpatient … 509    542    629    619    596    581    539    524    531   
 8 Hospital    422    467    515    529    516    511    469    440    447   
 9 Residentia… 224    233    299    229    225    199    198    213    217   
10 NONSPECIAL… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   3430   3465  
11 Education   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2931   2957  
12 School Soc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   2286   2214  
13 Special Sc… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   975    1054  
14 General Me… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
15 Pediatrici… 657    732    840    810    694    692    710    605    601   
16 Juvenile J… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
17 Juvenile D… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   109    80    
18 Child Welf… <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>  
19 Foster Car… 157    179    158    143    129    114    118    92     108   
20 SPECIALTY … <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   <NA>   1226   1283  
# … with 8 more variables: `2011` <chr>, `2012` <chr>, `2013` <chr>,
#   `2014` <chr>, `2015` <chr>, `2016` <chr>, `2017` <chr>, `2018` <chr>

Our table is looking much better!

We also want to change our values to be numeric as opposed to character so that we can use them in mathematical functions. We can use the base as.numeric() function. Again we will use the across() function to indicate what variables we wish to mutate.

# A tibble: 20 x 18
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>        <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
 1 SPECIALTY …   2898   3065   3348   3362   3255   3104   3129   2925   2920
 2 Outpatient    2662   2795   3015   3048   2931   2787   2837   2650   2635
 3 Private Th…   2254   2347   2523   2573   2416   2365   2408   2296   2265
 4 Mental Hea…    611    635    716    657    587    583    567    537    547
 5 Partial Da…    440    425    439    449    471    416    374    340    362
 6 InHome The…    693    656    762    731    719    707    716    657    674
 7 Inpatient …    509    542    629    619    596    581    539    524    531
 8 Hospital       422    467    515    529    516    511    469    440    447
 9 Residentia…    224    233    299    229    225    199    198    213    217
10 NONSPECIAL…     NA     NA     NA     NA     NA     NA     NA   3430   3465
11 Education       NA     NA     NA     NA     NA     NA     NA   2931   2957
12 School Soc…     NA     NA     NA     NA     NA     NA     NA   2286   2214
13 Special Sc…     NA     NA     NA     NA     NA     NA     NA    975   1054
14 General Me…     NA     NA     NA     NA     NA     NA     NA     NA     NA
15 Pediatrici…    657    732    840    810    694    692    710    605    601
16 Juvenile J…     NA     NA     NA     NA     NA     NA     NA     NA     NA
17 Juvenile D…     NA     NA     NA     NA     NA     NA     NA    109     80
18 Child Welf…     NA     NA     NA     NA     NA     NA     NA     NA     NA
19 Foster Car…    157    179    158    143    129    114    118     92    108
20 SPECIALTY …     NA     NA     NA     NA     NA     NA     NA   1226   1283
# … with 8 more variables: `2011` <dbl>, `2012` <dbl>, `2013` <dbl>,
#   `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>, `2018` <dbl>

We would also like to add a type and subtype variable, that specifies the general categories of settings where services were received, as well as remove a couple of rows that are completely empty. These are the rows where the first column values are Genearl_Medicine and Juvenile_Justice, and Child Welfare. If we look at the website, we can see that these were leading lines with no data.

First we will add the type and subtype variables using the mutate function.

We also want to add a variable with shorter names for labels in plots and statistical output.

We can remove the empty rows using the filter() function of the dplyr package. We can specify that we don’t want to keep these rows by using the != not equal to operator.

# A tibble: 20 x 21
   MHS_setting `2002` `2003` `2004` `2005` `2006` `2007` `2008` `2009` `2010`
   <chr>        <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
 1 SPECIALTY …   2898   3065   3348   3362   3255   3104   3129   2925   2920
 2 Outpatient    2662   2795   3015   3048   2931   2787   2837   2650   2635
 3 Private Th…   2254   2347   2523   2573   2416   2365   2408   2296   2265
 4 Mental Hea…    611    635    716    657    587    583    567    537    547
 5 Partial Da…    440    425    439    449    471    416    374    340    362
 6 InHome The…    693    656    762    731    719    707    716    657    674
 7 Inpatient …    509    542    629    619    596    581    539    524    531
 8 Hospital       422    467    515    529    516    511    469    440    447
 9 Residentia…    224    233    299    229    225    199    198    213    217
10 NONSPECIAL…     NA     NA     NA     NA     NA     NA     NA   3430   3465
11 Education       NA     NA     NA     NA     NA     NA     NA   2931   2957
12 School Soc…     NA     NA     NA     NA     NA     NA     NA   2286   2214
13 Special Sc…     NA     NA     NA     NA     NA     NA     NA    975   1054
14 General Me…     NA     NA     NA     NA     NA     NA     NA     NA     NA
15 Pediatrici…    657    732    840    810    694    692    710    605    601
16 Juvenile J…     NA     NA     NA     NA     NA     NA     NA     NA     NA
17 Juvenile D…     NA     NA     NA     NA     NA     NA     NA    109     80
18 Child Welf…     NA     NA     NA     NA     NA     NA     NA     NA     NA
19 Foster Car…    157    179    158    143    129    114    118     92    108
20 SPECIALTY …     NA     NA     NA     NA     NA     NA     NA   1226   1283
# … with 11 more variables: `2011` <dbl>, `2012` <dbl>, `2013` <dbl>,
#   `2014` <dbl>, `2015` <dbl>, `2016` <dbl>, `2017` <dbl>, `2018` <dbl>,
#   type <chr>, subtype <chr>, short_label <chr>

Finally, we would like to change the shape of our table so that we have a new column that represents the year and a new column that represents the value for that year. To do so we will be making our table “longer”, meaning that it will have fewer rows and more columns. See here for more information about different table formats, typically referred to as wide and long or sometimes narrow.

We will use the pivot_longer() function of the tidyr package to change the shape of our table.

There are 3 main arguments in this function:
1) cols - which specifies what columns to collapse
2) names_to - which specifies the name of the new column that will be created that will contain the column names of the columns you are collapsing
3) values_to - which specifies the name of the new column that will be created that will contain the values from the columns you are collapsing

To specify that we want to collapse all columns except the MHS_setting column we can again use the minus sign. Finally, we will make the Year variable numeric as well.

# A tibble: 340 x 6
   MHS_setting                type     subtype       short_label     Year Number
   <chr>                      <chr>    <chr>         <chr>          <dbl>  <dbl>
 1 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2002   2898
 2 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2003   3065
 3 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2004   3348
 4 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2005   3362
 5 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2006   3255
 6 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2007   3104
 7 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2008   3129
 8 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2009   2925
 9 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2010   2920
10 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty tot…  2011   3101
# … with 330 more rows

We can see that our table is now much longer - as we have 340 rows!

Question Opportunity

Why do we have 340 rows now?

Now we see that the Year and Number variables are of class double because of the <dbl> under the column name.

Let’s take a look at what the rest of the tables contain:

Table Details
Table 11.1A Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Numbers in Thousands, 2002-2018
Table 11.1B Settings Where Mental Health Services Were Received in Past Year among Persons Aged 12 to 17: Percentages, 2002-2018
Table 11.2A Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2004-2018
Table 11.2B Major Depressive Episode in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2004-2018
Table 11.3A Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Numbers in Thousands, 2006-2018
Table 11.3B Major Depressive Episode with Severe Impairment in Past Year among Persons Aged 12 to 17, by Demographic Characteristics: Percentages, 2006-2018
Table 11.4A Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Numbers in Thousands, 2004-2018
Table 11.4B Receipt of Treatment for Depression in Past Year among Persons Aged 12 to 17 with Major Depressive Episode in Past Year, by Demographic Characteristics: Percentages, 2004-2018

OK, so the next table is very similar to Table11.1A, while the remaining tables have information about demographics.

As a reminder here are all of the steps that we performed to wrangle table11.1a:

table11.1a %<>%
  dplyr::as_tibble() %>%
  slice(1:(n()-1))%>%
  dplyr::na_if("nc") %>%
  dplyr::na_if("--") %>%
  dplyr::na_if("") %>%
  dplyr::na_if("*")%>%
  dplyr::rename(MHS_setting = 
                  `Setting Where Mental Health ServiceWas Received`) %>%
  mutate(MHS_setting = 
         str_remove_all(string = MHS_setting, 
                       pattern = "[:digit:]|\r\n|[:punct:]|")) %>%
  mutate(MHS_setting = 
         str_replace_all(string = MHS_setting,
                        pattern = "[:blank:]{1,}", 
                    replacement = " ")) %>%
  mutate(dplyr::across(.cols = -MHS_setting,
                stringr::str_remove_all, "a|,")) %>%
  mutate(across(-MHS_setting, as.numeric)) %>%
  mutate(type = c(rep("Specialty", 9), rep("Nonspecialty", 11))) %>%
  mutate(subtype =c("Specialty_total", 
                    rep("Outpatient", 5), 
                    rep("Inpatient", 3), 
                    "Nonspecialty_total", 
                    rep("Education", 3), 
                    rep("General_medicine", 2),
                    rep("Juvenile_Justice", 2),
                    rep("Child_Welfare", 2), 
                    "combination")) %>%
  mutate(short_label = c("Specialty total", "Outpatient total", "Therapist", "Clinic", "Day program", "In-home Therapist", "Inpatient total", "Hospital", "Residential Center", "Nonspecialty total", "School total", "School Therapist", "School Program", "General Medicine", "Family Dr", "Justice System", "Justice System", "Welfare", "Fostercare", "Specialty Combination")) %>%
  dplyr::filter(MHS_setting != "General_Medicine") %>%
  dplyr::filter(MHS_setting != "Juvenile_Justice") %>%
  dplyr::filter(MHS_setting != "Child_Welfare") %>%
    tidyr::pivot_longer(cols = contains("20"), 
                  names_to = "Year",
                 values_to = "Number") %>%
   mutate(Year = as.numeric(Year))

Now we want to wrangle table11.1B which is formatted the most similarly. To do so we can simply run these steps on the using the table11.1B as the input. For the sake of education however, we will show you how you could make a function if we had several more similar tables to wrangle. This will also make it easier to write a function to wrangle the other demographic tables.

Last time we wrote a function in this case study, we only had one input in our function. This time we will have several inputs. We will have the table that we want to wrangle as TABLE, a new name for the first column called new_col, and an input called pivot_col which will be the name of the column that will be created after pivoting that will take the values from each of the years.

We will also add code to remove all rows that have only NA values, this means we don’t need to know what rows ahead of time.

To do this we will use the filter() and select() functions of the dplyr package.

We will calculate a sum of the count of NA values across the rows for the numeric columns (the columns for each year) using the base rowSums() function.

To do this we first select the columns that are numeric using: select(., is.numeric), where the . refers to the table after all the previous wrangling steps in our function.

Then we get a true or false statement about which columns have NA values with the base is.na() function (this requires numeric values).

Then we calculate the sum using the base rowSums() function.

Altogether this looks like this: rowSums(is.na(select(., is.numeric))). Finally we compare this to the number of columns that are numeric by using: length(select(., is.numeric))), with the idea that if the number of NA values is less than the number of columns that could have NA values, then we know it is not an empty row.

Note that if we were using the summarise() or mutate() function or the dplyr package, then we could use the across() function of the dplyr package to select what columns we wanted to use in our calculation.

Now we can apply the function to table11.1b.

Table11.1b

# A tibble: 289 x 6
   MHS_setting                type     subtype       short_label    Year Percent
   <chr>                      <chr>    <chr>         <chr>         <dbl>   <dbl>
 1 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2002    11.8
 2 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2003    12.4
 3 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2004    13.4
 4 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2005    13.4
 5 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2006    13  
 6 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2007    12.4
 7 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2008    12.7
 8 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2009    12  
 9 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2010    12.1
10 SPECIALTY MENTAL HEALTH S… Special… Specialty_to… Specialty to…  2011    12.6
# … with 279 more rows

Great!

What about the subsequent tables?

Demographic Tables

All of the rest of the tables have demographic information and have this general structure:

In these tables we have age groups in our first column so we don’t want to remove digits or punctuation marks anymore so we need to modify our function a bit to remove that step.

We also want to add the word Age and an underscore in front of the age group listed in the tables. We can use the str_replace() function of the stringr package, because now we want to only replace the first instance of 1 with Age_1.

We also plan to replace the first column name with Demographic for all of the tables.

We also want to create a new variable that list the subgroups.

We will also want to only wrangle the data up to the point that we change the shape of the data, so that we can check how the data looks first.

from Michael

We use the function to wrangle the next set of tables. We will also add a column to describe what the data is about which will be helpful for merging the data later.

Rows: 14
Columns: 18
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2004`      <dbl> 2225, 445, 783, 997, 637, 1588, 1848, 1413, 287, 13, NA, …
$ `2005`      <dbl> 2191, 417, 811, 964, 571, 1620, 1802, 1390, 288, 10, NA, …
$ `2006`      <dbl> 1970, 383, 684, 902, 539, 1431, 1614, 1220, 245, 12, NA, …
$ `2007`      <dbl> 2016, 337, 705, 974, 586, 1430, 1691, 1284, 292, 7, NA, 6…
$ `2008`      <dbl> 2027, 366, 706, 955, 540, 1487, 1681, 1266, 261, 13, NA, …
$ `2009`      <dbl> 1954, 330, 741, 883, 577, 1377, 1594, 1180, 285, 9, NA, 7…
$ `2010`      <dbl> 1911, 330, 706, 876, 536, 1375, 1537, 1186, 236, 10, 1, 5…
$ `2011`      <dbl> 2011, 312, 710, 989, 566, 1446, 1586, 1167, 238, 15, NA, …
$ `2012`      <dbl> 2213, 420, 844, 950, 581, 1632, 1648, 1231, 269, 7, NA, 4…
$ `2013`      <dbl> 2587, 470, 1025, 1091, 657, 1930, 1970, 1449, 289, 7, NA,…
$ `2014`      <dbl> 2751, 548, 986, 1217, 710, 2042, 2123, 1578, 306, 11, NA,…
$ `2015`      <dbl> 3031, 587, 1163, 1281, 725, 2306, 2323, 1742, 302, NA, NA…
$ `2016`      <dbl> 3089, 548, 1115, 1427, 786, 2303, 2366, 1781, 301, 16, NA…
$ `2017`      <dbl> 3214, 516, 1200, 1498, 845, 2369, 2419, 1785, 313, 24, NA…
$ `2018`      <dbl> 3482, 632, 1250, 1600, 946, 2537, 2601, 1905, 334, 23, NA…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race/Ethnici…
$ data_type   <chr> "Major_Depressive_Episode", "Major_Depressive_Episode", "…
Rows: 14
Columns: 18
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2004`      <dbl> 9.0, 5.4, 9.2, 12.3, 5.0, 13.1, 8.9, 9.2, 7.7, 7.8, NA, 8…
$ `2005`      <dbl> 8.8, 5.2, 9.5, 11.5, 4.5, 13.3, 8.7, 9.1, 7.6, 6.1, NA, 6…
$ `2006`      <dbl> 7.9, 4.9, 7.9, 10.7, 4.2, 11.8, 7.9, 8.2, 6.4, 9.3, NA, 7…
$ `2007`      <dbl> 8.2, 4.3, 8.4, 11.5, 4.6, 11.9, 8.4, 8.7, 7.8, 4.6, NA, 6…
$ `2008`      <dbl> 8.3, 4.9, 8.5, 11.2, 4.3, 12.5, 8.5, 8.8, 7.1, 10.1, NA, …
$ `2009`      <dbl> 8.1, 4.6, 8.8, 10.4, 4.7, 11.7, 8.2, 8.4, 7.9, 7.5, NA, 7…
$ `2010`      <dbl> 8.0, 4.3, 9.0, 10.6, 4.4, 11.9, 8.1, 8.6, 6.8, 7.4, 1.8, …
$ `2011`      <dbl> 8.2, 4.1, 8.6, 11.7, 4.5, 12.1, 8.3, 8.6, 7.0, 11.4, NA, …
$ `2012`      <dbl> 9.1, 5.4, 10.2, 11.4, 4.7, 13.7, 8.7, 9.1, 7.9, 5.2, NA, …
$ `2013`      <dbl> 10.7, 6.1, 12.4, 13.2, 5.3, 16.2, 10.4, 10.9, 8.6, 4.5, N…
$ `2014`      <dbl> 11.4, 7.2, 11.9, 14.6, 5.7, 17.3, 11.3, 12.0, 9.1, 6.9, N…
$ `2015`      <dbl> 12.5, 7.8, 13.8, 15.5, 5.8, 19.5, 12.5, 13.4, 9.0, NA, NA…
$ `2016`      <dbl> 12.8, 7.3, 13.3, 17.2, 6.4, 19.4, 12.8, 13.8, 9.1, 11.5, …
$ `2017`      <dbl> 13.3, 6.9, 14.5, 17.7, 6.8, 20.0, 13.1, 14.0, 9.5, 16.3, …
$ `2018`      <dbl> 14.4, 8.4, 15.3, 19.0, 7.7, 21.5, 14.2, 15.1, 10.3, 15.2,…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race/Ethnici…
$ data_type   <chr> "Major_Depressive_Episode", "Major_Depressive_Episode", "…
Rows: 13
Columns: 16
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2006`      <dbl> 1358, 211, 518, 629, 335, 1023, 1118, 871, 150, 9, 54, 32…
$ `2007`      <dbl> 1371, 200, 500, 671, 386, 986, 1141, 873, 193, 4, 39, 32,…
$ `2008`      <dbl> 1460, 239, 505, 716, 359, 1101, 1226, 944, 171, 8, 44, 50…
$ `2009`      <dbl> 1404, 235, 521, 648, 391, 1013, 1150, 858, 204, 5, 48, 31…
$ `2010`      <dbl> 1350, 232, 479, 639, 395, 954, 1093, 853, 157, 7, 44, 30,…
$ `2011`      <dbl> 1388, 218, 487, 683, 397, 991, 1113, 799, 183, 13, 60, 57…
$ `2012`      <dbl> 1544, 285, 590, 669, 373, 1172, 1152, 883, 164, 4, 30, 64…
$ `2013`      <dbl> 1868, 314, 752, 801, 435, 1432, 1425, 1046, 207, 6, 98, 6…
$ `2014`      <dbl> 1990, 375, 707, 909, 461, 1529, 1540, 1167, 214, 8, 80, 6…
$ `2015`      <dbl> 2129, 388, 826, 915, 477, 1652, 1651, 1258, 198, NA, 67, …
$ `2016`      <dbl> 2168, 354, 789, 1025, 539, 1629, 1703, 1290, 196, 8, 118,…
$ `2017`      <dbl> 2265, 332, 861, 1072, 581, 1684, 1694, 1256, 233, 6, 101,…
$ `2018`      <dbl> 2423, 382, 891, 1150, 628, 1795, 1841, 1354, 225, NA, 127…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race/Ethnici…
$ data_type   <chr> "Severe_Major_Depressive_Episode", "Severe_Major_Depressi…
Rows: 13
Columns: 16
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2006`      <dbl> 5.5, 2.7, 6.0, 7.5, 2.6, 8.4, 5.5, 5.8, 3.9, 6.6, 5.3, 8.…
$ `2007`      <dbl> 5.5, 2.5, 6.0, 7.9, 3.0, 8.2, 5.7, 5.9, 5.1, 2.6, 3.9, 7.…
$ `2008`      <dbl> 6.0, 3.2, 6.1, 8.4, 2.9, 9.3, 6.2, 6.5, 4.6, 6.5, 4.7, 10…
$ `2009`      <dbl> 5.8, 3.2, 6.2, 7.7, 3.2, 8.6, 5.9, 6.1, 5.7, 4.3, 5.0, 6.…
$ `2010`      <dbl> 5.7, 3.0, 6.1, 7.7, 3.2, 8.2, 5.7, 6.2, 4.5, 5.4, 4.3, 5.…
$ `2011`      <dbl> 5.7, 2.8, 5.9, 8.1, 3.2, 8.3, 5.8, 5.9, 5.4, 9.8, 5.0, 8.…
$ `2012`      <dbl> 6.3, 3.7, 7.1, 8.0, 3.0, 9.8, 6.1, 6.5, 4.8, 2.6, 2.6, 9.…
$ `2013`      <dbl> 7.7, 4.1, 9.1, 9.7, 3.5, 12.0, 7.6, 7.8, 6.2, 3.8, 8.1, 8…
$ `2014`      <dbl> 8.2, 4.9, 8.5, 10.9, 3.7, 13.0, 8.2, 8.9, 6.4, 4.9, 6.6, …
$ `2015`      <dbl> 8.8, 5.1, 9.8, 11.1, 3.8, 14.0, 8.9, 9.7, 5.9, NA, 5.5, 1…
$ `2016`      <dbl> 9.0, 4.7, 9.4, 12.4, 4.4, 13.7, 9.2, 10.0, 6.0, 5.7, 9.3,…
$ `2017`      <dbl> 9.4, 4.4, 10.4, 12.7, 4.7, 14.2, 9.2, 9.8, 7.1, 3.9, 7.9,…
$ `2018`      <dbl> 10.0, 5.1, 10.9, 13.7, 5.1, 15.2, 10.1, 10.7, 6.9, NA, 9.…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race/Ethnici…
$ data_type   <chr> "Severe_Major_Depressive_Episode", "Severe_Major_Depressi…
Rows: 11
Columns: 18
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2004`      <dbl> 895, 169, 278, 448, 239, 656, 756, 633, 82, NA, 139
$ `2005`      <dbl> 822, 136, 329, 357, 193, 629, 700, 544, 113, NA, 122
$ `2006`      <dbl> 760, 133, 263, 364, 189, 571, 634, 502, 70, NA, 126
$ `2007`      <dbl> 782, 137, 259, 386, 214, 568, 691, 545, 116, NA, 91
$ `2008`      <dbl> 764, 122, 236, 405, 183, 581, 658, 545, 85, NA, 105
$ `2009`      <dbl> 673, 98, 244, 331, 168, 505, 555, 444, 67, NA, 118
$ `2010`      <dbl> 721, 106, 271, 343, 171, 549, 577, 487, 54, NA, 144
$ `2011`      <dbl> 769, 112, 258, 400, 199, 570, 645, 482, 97, NA, 125
$ `2012`      <dbl> 813, 127, 307, 379, 163, 650, 642, 500, 90, NA, 171
$ `2013`      <dbl> 977, 181, 376, 420, 193, 784, 753, 598, 83, NA, 224
$ `2014`      <dbl> 1122, 194, 394, 535, 265, 857, 918, 723, 123, NA, 204
$ `2015`      <dbl> 1186, 185, 472, 530, 262, 924, 936, 702, 127, 55, 251
$ `2016`      <dbl> 1249, 189, 455, 605, 260, 989, 1008, 799, 102, NA, 241
$ `2017`      <dbl> 1330, 193, 453, 684, 274, 1056, 1072, 847, 110, 62, 258
$ `2018`      <dbl> 1432, 251, 514, 667, 351, 1081, 1100, 870, 115, 48, 332
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race/Ethnici…
$ data_type   <chr> "treatment", "treatment", "treatment", "treatment", "trea…
Rows: 11
Columns: 18
$ Demographic <chr> "TOTAL", "Age_12-13", "Age_14-15", "Age_16-17", "Male", "…
$ `2004`      <dbl> 40.3, 38.2, 35.5, 45.0, 37.7, 41.3, 41.0, 44.9, 28.9, NA,…
$ `2005`      <dbl> 37.8, 32.9, 41.1, 37.1, 34.1, 39.0, 39.0, 39.3, 39.3, NA,…
$ `2006`      <dbl> 38.8, 35.1, 38.4, 40.7, 35.3, 40.2, 39.5, 41.3, 29.1, NA,…
$ `2007`      <dbl> 39.0, 41.5, 36.8, 39.8, 36.7, 40.0, 41.1, 42.7, 39.7, NA,…
$ `2008`      <dbl> 37.7, 33.5, 33.6, 42.4, 34.0, 39.1, 39.3, 43.1, 32.4, NA,…
$ `2009`      <dbl> 34.6, 30.0, 33.2, 37.5, 29.2, 36.9, 35.0, 37.7, 23.9, NA,…
$ `2010`      <dbl> 37.8, 32.5, 38.4, 39.3, 32.0, 40.1, 37.6, 41.1, 23.0, NA,…
$ `2011`      <dbl> 38.4, 36.3, 36.3, 40.5, 35.3, 39.5, 40.7, 41.4, 41.0, NA,…
$ `2012`      <dbl> 37.0, 30.7, 36.6, 40.0, 28.3, 40.1, 39.0, 40.7, 33.5, NA,…
$ `2013`      <dbl> 38.1, 39.1, 37.2, 38.6, 29.7, 40.9, 38.5, 41.6, 28.6, NA,…
$ `2014`      <dbl> 41.2, 35.9, 40.1, 44.4, 37.7, 42.4, 43.5, 46.1, 40.6, NA,…
$ `2015`      <dbl> 39.3, 31.9, 40.6, 41.5, 36.3, 40.3, 40.5, 40.6, 42.0, 46.…
$ `2016`      <dbl> 40.9, 35.3, 41.3, 42.6, 33.5, 43.4, 42.9, 45.1, 34.5, NA,…
$ `2017`      <dbl> 41.5, 37.6, 37.9, 45.8, 32.5, 44.8, 44.4, 47.5, 35.1, 44.…
$ `2018`      <dbl> 41.4, 40.7, 41.2, 41.8, 37.5, 42.9, 42.6, 46.1, 34.6, 34.…
$ subgroup    <chr> "Total", "Age", "Age", "Age", "Sex", "Sex", "Race/Ethnici…
$ data_type   <chr> "treatment", "treatment", "treatment", "treatment", "trea…

Great! All of the demographic tables look good.

Now let’s combine the count data (the “a” tables) and the percent data (the “b” tables) using the bind_rows() function of the dplyr package. Which will append each of the subsequent tables together.

We can use the distinct() function of the dplyr package to check that we indeed have all the data types now in these larger tibbles.

# A tibble: 3 x 1
  data_type                      
  <chr>                          
1 Major_Depressive_Episode       
2 Severe_Major_Depressive_Episode
3 treatment                      
# A tibble: 3 x 1
  data_type                      
  <chr>                          
1 Major_Depressive_Episode       
2 Severe_Major_Depressive_Episode
3 treatment                      

Great!

Now we will reformat both the counts and percents data to be in the long format using pivot_longer() once again.

Now that we’ve wrangled the data, we can go ahead and proceed with our analysis.

Data Analysis


Recall what our main questions were:

Our main questions:

  1. How have depression rates in American youth changed since 2004, according to the NSDUH data? How have rates differed between different youth subgroups (age, gender, ethnicity)?
  2. Do mental health services appear to be reaching more youths? Again, how have rates differed between different youth subgroups (age, gender, ethnicity)?

We are specifically interested in how the frequency of recent major depressive episodes among youths differ compared to those in 2004. We are also interested how different groups differ. We will start with examining how male and females differ across time.

Since we have counts for the two sexes: males and females, and for the two years of interest, 2004 and 2018, we can conduct a Pearson’s chi-squared test for independence, which is also written like this: \({\chi}^2\).

This will allow us to compare if the frequencies of major depressive episodes differs from what we would expect by chance if the variables years and sex were independent.

The null hypothesis is that the variables are independent or that the difference in the proportions is equal to zero. Thus we want to test if sex and year are independent. In other words, we want to know if sex influences the number of major depressive episodes in 2004 and 2018. Or stated yet another way, Are major depressive episode counts across the two years associated with sex.

According to wikipedia:

Pearson’s chi-square test is used to determine whether there is a statistically significant difference between the expected frequencies and the observed frequencies in one or more categories of a contingency table.

Thus, to conduct this statistical test, we need to produce a contingency table, which in this case could also be called a 2x2 table, which is the simplest kind of contingency table (only two levels for two variables).

Here is an example of another 2x2 table:

# A tibble: 3 x 4
  Sex    Righthanded Lefthanded Total
  <chr>        <dbl>      <dbl> <dbl>
1 Male            41          9    50
2 Female          47          3    50
3 Total           88         12   100

Here are all the observed values.

We can see that there are two variables: Sex and Handedness and each have two levels (male and female for sex and right and left for handedness). The table also includes totals of each of the 4 possible groups as well as the overall total.

Now let’s create a table of expected values assuming sex and handedness are independent.

The total right-handed is 88 out of 100 which is equal to 88%. The total left-handed is 12 out of 100 which is equal to 12%.

Thus if each sex had the same amount of right-handedness and left-handedness, we would expect 88% of the males to be right-handed and 12 % to be left-handed; and we would expect the exact same proportions of 88% right-handed and 12% left-handed for the females.

Since we have 50 males and 50 females and 12% of 50 is 6 and 88% of 50 is 44, we would thus have the following table of expected frequencies:

# A tibble: 3 x 4
  Sex    Righthanded Lefthanded Total
  <chr>        <dbl>      <dbl> <dbl>
1 Male            44          6    50
2 Female          44          6    50
3 Total           88         12   100

The \({\chi}^2\) is calculated like so:

\[{\chi}^2=\sum_{j=1}^{m} \frac{(O_j - E_j)^2}{E_j}\]

Where \(O_j = j^{th}\) observed count and \(E_j = j^{th}\) expected count for the jth cell of a contingency table with \(m\) cells.

The degrees of freedom (\(df\)) is calculated like so: \(df= (r-1)(c-1)\).

Where \(r\) = # of rows and \(c\) = the # of columns.

So to calculate the \({\chi}^2\) for handedness and sex manually, we can do the following for each of the four values in the table (besides the totals) like this:

\({\chi}^2\) = fraction of the square difference of the observed minus the expected, divided by expected for right-handed males + the same for left-handed males + the same for right-handed females + the same for left-handed females

This is equal to :

\[{\chi}^2 = \frac{(41-44)^2}{44} + \frac{(9-6)^2}{6}+ \frac{(47-44)^2}{44}+ \frac{(3-6)^2}{6}\]

Which is equal to:

\({\chi}^2\) = 3.4090909

Where the degrees of freedom = \(df = 92-1)(2-1) = 1\)

What does this mean? We need to consult a chi-square distribution to determine what the p-value is and if this is significant.

#### [source

This website has a simple way to check this, without requiring you to get out a ruler and consult this plot. Note on this website the notation for \(df\) is \({\nu}\).

Plugging in 3.409091 as \({\chi}^2\) and 1 as \({\nu}\), we get a \(p-value\) of 0.06484.

Thus we do not have enough evidence to reject the null hypothesis. Therefore, we conclude that sex and handedness do appear to be independent.

See here for a more thorough explanation of the chi-square test.

Now let’s create a contingency table with our own data and see how we can implement this test in R.

It is critical that we use the counts data, and not the percentage data for our analysis, as the \({\chi}^2\) requires counts.

We will filter the count data for the Major_Depressive_Episode data, as well as for the Male and Female data from 2004 and 2018.

The following code subsets the data we need and makes the necessary manipulations so that the units of observation are appropriate. If we take a look at the title of the table we can see that the numbers in the table represent individuals by the thousands.

The resulting object contains all the values we need for out contingency table.

# A tibble: 4 x 5
  Demographic subgroup data_type                 Year  Number
  <chr>       <chr>    <chr>                    <dbl>   <dbl>
1 Male        Sex      Major_Depressive_Episode  2004  637000
2 Male        Sex      Major_Depressive_Episode  2018  946000
3 Female      Sex      Major_Depressive_Episode  2004 1588000
4 Female      Sex      Major_Depressive_Episode  2018 2537000

A contingency table can now be produced from this data which is in long format by transforming the data to wide format and re-purposing some values as row names. To reformat the data to wide format we can use the pivot_wider() function of the tidyr package.

For this function there are several important arguments:
1) names_from - this is the variable where the names of new columns will come from 2) values_from - this is the variable where the values for the new columns will come from 3) names_prefix - if we want to add a prefix to the new columns we can do so using this argument

So in our case we want to spread out the year data into two columns thus the names will come from the Year variable and the values will come from the Number variable. We want to add the word Year to the new columns. We also want the remove the subgroup and data_type variables and only keep the Demographic, Year, and Number variables. To do so we can use the select() function. Fin

# A tibble: 2 x 3
  Demographic Year2004 Year2018
  <chr>          <dbl>    <dbl>
1 Male          637000   946000
2 Female       1588000  2537000

Now we can use the column_to_rownames() function of the tibble package to make the Demographic variable levels the row names. Otherwise we would need to select the numeric columns to perform the stats test.

       Year2004 Year2018
Male     637000   946000
Female  1588000  2537000

Note that a contingency table would also have totals for all groups as well, but this is not necessary for the stats::chisq.test() function.

The chi-squared test for independence can be conducted using the stats::chisq.test() function.


    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.2a
X-squared = 1461.2, df = 1, p-value < 2.2e-16

We see that the p-value is very small, which suggests that sex does influence the count of major depressive episodes across time.

How about for severe major depressive episodes?

       Year2009 Year2018
Male     391000   628000
Female  1013000  1795000

    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.3a
X-squared = 1696, df = 1, p-value < 2.2e-16

There also appears to be an influence of sex on the rate of severe major depressive episodes across the years.

How about treatment?

       Year2009 Year2018
Male     168000   351000
Female   505000  1081000

    Pearson's Chi-squared test with Yates' continuity correction

data:  chi_square_11.4a
X-squared = 50.256, df = 1, p-value = 1.349e-12

There also appears to be an influence of sex on the rate at which youths received treatment across the two years.

avocado.. I think it makes sense to move the visualization section first… and use it to motivate that analysis from the year 2010 and of male and females…

Data Visualization


OK, so now we are going to make some visualizations to further explore our questions of interest.

We are going to use the ggplot2 package to create our plots.

Click here for an introduction about this package if you are new to using ggplot2

The ggplot2 package is generally intuitive for beginners because it is based on a grammar of graphics or the gg in ggplot2. The idea is that you can construct many sentences by learning just a few nouns, adjectives, and verbs. There are specific “words” that we will need to learn and once we do, you will be able to create (or “write”) hundreds of different plots.

The critical part to making graphics using ggplot2 is the data needs to be in a tidy format. Given that we have just spent time putting our data in tidy format, we are primed to take advantage of all that ggplot2 has to offer!

We will show how it is easy to pipe tidy data (output) as input to other functions that create plots. This all works because we are working within the tidyverse.

What is the ggplot() function? As explained by Hadley Wickham:

The grammar tells us that a statistical graphic is a mapping from data to aesthetic attributes (colour, shape, size) of geometric objects (points, lines, bars). The plot may also contain statistical transformations of the data and is drawn on a specific coordinates system.

ggplot2 Terminology * ggplot - the main function where you specify the dataset and variables to plot (this is where we define the x and y variable names) * geoms - geometric objects * e.g. geom_point(), geom_bar(), geom_line(), geom_histogram() * aes - aesthetics * shape, transparency, color, fill, line types * scales - define how your data will be plotted * continuous, discrete, log, etc

The function aes() is an aesthetic mapping function inside the ggplot() object. We use this function to specify plot attributes (e.g. x and y variable names) that will not change as we add more layers.

Anything that goes in the ggplot() object becomes a global setting. From there, we use the geom objects to add more layers to the base ggplot() object. These will define what we are interested in illustrating using the data.

Major Depressive Episodes in past year

We will start by taking a look at the rate of major depressive episodes among youths over time of the various demographic groups.

OK, we will start out by using the ggplot() function to specify what data we would like to plot on each axis. We will also indicate that would like to use the Demographic variable to group our data and to color our data. This is our first layer of the plot, thus for subsequent layers we need to use a plus sign +.

Next we will use the geom_line() function of the ggplot2 package to specify that we would like to create a line plot.

Then we will add labels for the title and subtitle using the labs() function of the ggplot2 package.

Finally we will move our legend to the bottom of the plot using the theme() function which helps us control various details about our plot.

This plot very difficult to read because there are so very many groups. Now let’s look at just the total across time. We can do so by first filtering our data for total values.

It would also nice to include every year in the x-axis. We can do so by using the scale_x_continuous() function which gives us greater control about how the x-axis is displayed.

Finally, we will drop the legend since we will only have one group using legend.position = "none" and we can change the angle of the x-axis text using axis.text.x = element_text(angle = 90) within the theme() function.

We will also make the line thicker using the size = argument for the geom_line() function.

The theme_linedraw() function changes the aesthetics of the plot. See here for a list of options.

We can see that there is a steep increase after around 2011:

Let’s add a different background color for the years since 2011. We can do so by adding a geom_rect() layer before we plot the line. We just need to specify the location of the rectangle on our plot.

Now let’s look at group differences.

To make sure our plot is not too overwhelming, let’s limit to only age and sex subgroups. Thus we will filter out the data about totals and different racial/ethnic groups for now. We will also use the facet_wrap() function to make subplots based on the demographic categories, which we put in a variable called subgroups earlier when we wrangled the data.

Nice! Now it is much easier to tell how each group has changed over time.

We can also add labels directly to the lines using the directlabels package. There are several methods to do so. See here for more information about the options for adding labels with this package. We will use the "far.from.others.borders" method so that our labels don’t overlap one another. We will also use dl.trans() of the directlabels package to move the labels slightly upward (y = y +0.35) and to the left (x = x -0.1). We will use the dl.move() function of the directlabels package to move one of the labels to a particular location.

This looks very clear now!

We can see that the majority of individuals that reported experiencing a major depressive episode in the past year were in an older age bracket. We can also see that the trend has been increasing for all three age brackets since roughly 2011.

We can also see an increase for both sexes since about 2011, but there is a steeper increase for females. Furthermore Females have a much higher rate than males for all years.

Let’s make the same plot with a different shaded background for the years of the increase like we did for the total plot.

So what might be accounting for this?

This cross-cultural review article published in 2012 suggests that aspects related to life-style due to modernity may be causing increased depression rates:

Modern populations are increasingly overfed, malnourished, sedentary, sunlight-deficient, sleep-deprived, and socially-isolated. These changes in lifestyle each contribute to poor physical health and affect the incidence and treatment of depression.

And although this may be true globally, the US has been arguably experiencing these modern lifestyle changes for years prior to this steep increase in 2011.

So what might have happened in the US around this time?

There is large amount of literature about how the use of smart phone and social media may have lead to increased depression rates. See this article which links to many scientific articles on the subject.

This has been a controversial topic due to conflicting findings, likely due to focus on different sites and aspects of social media across different studies.

The article points out that the true relationship between social media use and depression may be nuanced. Some individuals who have high face-to-face levels of interaction or lack of the opportunity to interact with others face-to-face (due to various barriers like geography), may actually experience lower risk for depression with more social media use.

Furthermore, different social media platforms may vary for their influence on depression.

Instagram was released in 2010 (which is around when our plot starts to show the upward increase in major depressive episodes, particularly in females) and according to the article:

Image-driven Instagram shows up in surveys as the platform that most leads young people to report feeling anxiety, depression and worries about body image.

Furthermore, it may be secondary effects of social media use, like less physical activity or less sleep that may increase the risk for depression.

Now let’s take a look at how the rate of major depressive episodes has changed across time for different racial/ethnic groups.

Since we have so many groups, we probably don’t want to directly label the lines this time. Instead, we will rely on the legend that will be automatically created.

We will use the the fct_reorder function of the forcats package to order the racial/ethnic groups in the legend based on the last value (using tail()) of the Percent variable.

We will also manually color our lines based on a color palette called viridis, which is more discernible for individuals with color-blindness. To do so we will use the scale_color_viridis_d() function of the ggplot2 package, which is intended for coloring discrete values.

Unfortunately, there is only one value for NHOPI group, thus since this is a line plot, we do not have enough points(2 at minimum) to create a line, so lets remove this group from the plot to remove the group from the legend.

# A tibble: 15 x 5
   Demographic subgroup       data_type                 Year Percent
   <chr>       <chr>          <chr>                    <dbl>   <dbl>
 1 NHOPI       Race/Ethnicity Major_Depressive_Episode  2004    NA  
 2 NHOPI       Race/Ethnicity Major_Depressive_Episode  2005    NA  
 3 NHOPI       Race/Ethnicity Major_Depressive_Episode  2006    NA  
 4 NHOPI       Race/Ethnicity Major_Depressive_Episode  2007    NA  
 5 NHOPI       Race/Ethnicity Major_Depressive_Episode  2008    NA  
 6 NHOPI       Race/Ethnicity Major_Depressive_Episode  2009    NA  
 7 NHOPI       Race/Ethnicity Major_Depressive_Episode  2010     1.8
 8 NHOPI       Race/Ethnicity Major_Depressive_Episode  2011    NA  
 9 NHOPI       Race/Ethnicity Major_Depressive_Episode  2012    NA  
10 NHOPI       Race/Ethnicity Major_Depressive_Episode  2013    NA  
11 NHOPI       Race/Ethnicity Major_Depressive_Episode  2014    NA  
12 NHOPI       Race/Ethnicity Major_Depressive_Episode  2015    NA  
13 NHOPI       Race/Ethnicity Major_Depressive_Episode  2016    NA  
14 NHOPI       Race/Ethnicity Major_Depressive_Episode  2017    NA  
15 NHOPI       Race/Ethnicity Major_Depressive_Episode  2018    NA  

Census Bureau definitions:
1) AIAN stands for American Indian and Alaska Native
2) NHOPI stands for Native Hawaiian or Other Pacific Islander

We can see that the group of individuals who reported as being two or more races, had the highest percentages of having a major depressive episode in the past year. Those group who reported as Black or African American had the lowest percentages. However, we can see that most of the racial/ethnic groups are fairly similar and we see an increasing for most groups since around 2011. Keep in mind the limitations listed in the Limitations section as you view these findings. It is possible that this group may be less likely to report experiencing symptoms of depression.

Major Depressive Episode with Severe Impairment

Now let’s take a look at how the rate of youths reporting having a major depressive episode with severe impairment has changed over time. See the What are the data? section about how severe impairment was defined.

We can see that the majority of individuals that reported experiencing a major depressive episode with severe impairment were in an older age bracket, however there appears to be a more dramatic change in the middle age group from 2011-2012. We can see a very steep increase in the data for the females after 2011, again this is much more steep than the increase seen for males over time.

Now let’s look at racial/ethnic groups.

Census Bureau definitions:
1) AIAN stands for American Indian and Alaska Native
2) NHOPI stands for Native Hawaiian or Other Pacific Islander

We see similar trends as we saw for the previous racial/ethnic group plot. The rate is highest for those who are two are more races and lowest for those who are Black or African American. The data for the AIAN group is sparse, so it is unclear if their levels would be lowest on the last year.

Receipt of treatment for depression for youths who had a major depressive episode

Now we will take a look at those who received treatment. First let’s look overall.

Overall roughly 40 percent of youths who self-reported experiencing a major depressive episode, also received treatment for depression.

This rate is increasing overtime like the trend of those who had a major depressive episode, yet the data is much more variable from one year to the next.

There seems to be an upward trend, but it isn’t nearly as much as the trend we saw for the increase of major depressive episodes. In general, the data seems to vary much more as well.

It looks as though youths who report as being white received the most care from mental health services.

Mental Health Services

We will also take a look at where youths are receiving treatment by using values from table11.1b which has the percentage values for counts presented in table11.1a.

We can use the str_detect() function of the stringr package to filter for the values of the short_label variable that has the word total in it.

We can see that youths appear to be receiving care in nonspecialty facilities at a slightly higher rate than that of specialty facilities. However, the rates appear to be very similar and the relative differences appear to be consistent across time.

Let’s take a look at subcategories of mental health services. So now we will filter for values within the short_label variable that do not contain the word “total” by using a ! in front of the str_dectect statement.

OK, so now we know how the rates of different subgroups compare for having a major depressive episode in the past year, having a major depressive episode with severe impairment, and receiving treatment. We also know where youths are typically getting treatment. But how do the rates of having a major depressive episode in the past year, having a major depressive episode with severe impairment, and receiving treatment compare within each group?

Overall outcomes by group

We can see that a large portion of individuals experiencing a major depressive episode have an episode with severe impairment for each group. Females have a higher rate of both types of episode and of treatment. Although females have more than double the rate of reported episodes, they receive a relatively similar rate of treatment as males for depression. This suggests that females are either more likely than males to self-report depression symptoms in surveys, or females may not be receiving as much care despite the larger need.

All age groups show a similar ratio of severe major depressive episodes for those that experienced an episode.

All racial and ethnic groups also show a similar rate of severe episodes relative to general episode rate. The rate of receiving treatment is fairly similar relative to the percentage of youths that reported having symptoms for each group.

Summary


Summary Plot

Let’s make a plot that summarizes our major findings.

We will use the ggdraw() function of this package. This allows you to add labels and other plot aspects on top of existing plots. Thus if we want to add a title element to our overall plot that we will add to a combined plot of our existing plots we can use ggdraw() to start and then the draw_label() function to add text.

We can also make a subtitle in the same way.

Now we will modify some of our existing plots using the theme() function as we did before to remove the x-axis title, to change the color of the axis text and the title size and color, as well as change the titles of the plots.

For this last plot we also want to get the legend and save it as a separate object so that we can add it to our plot grid in a way that doesn’t shrink the size of our plot to accommodate the legend. We can use the get_legend() function of the cowplot package to do this. However, beforehand, we also want to change the way the legend is displayed. We can use the guides() function of the ggplot2 package to modify the legend to specify that we want the legend to be displayed in 2 rows like so guides(guide_legend(nrow = 2)).

Now we will remove the legend for this plot:

OK, now we are ready to start putting our plots together using the plot_grid() function of the cowplot package.

It is helpful to first make rows by combining the plots that we want to be displayed next to each other and then combining these with the title and subtitle, called forward.

We can use the rel_widths argument to modify how wide each plot is displayed.

Now we can combine everything together using plot_grid() yet again. Now that we have rows, we can combine everything as a single column and easily modify the relative heights using the rel_heights() function so that our title, subtitle and legend are all relative short relative to the plots. We will make the first row half the height of the second row.

Finally, we will use the png() function of the grDevices package which is automatically loaded in RStudio sessions to save the plot. We will use the here() function of the here package, to specify that we want to save it in the img directory and call it mainplot.png. We can also use this function to specify the resolution with res and in doing so, we need to save the image with size specifications to make it larger.

The dev.off() function is necessary to close the graphics device. This is good practice to allow you to create another plot again later.

avocado: I want to add something about self-reporting bias to the objectives

Synopsis

In this case study we evaluated self-reported measures of depression symptoms among youths age 12-17 in the United States, as well as the rate of youths receiving treatment for depression. We learned how to scrape data directly from the web using the rvest package and we learned how to perform and interpret a chi-square test using the chisq.test() function of the stats package.

By analyzing and plotting our data, it is clear that depression rates appear to be increasing, particularly since 2011. However, it is possible that respondents had similar rates in previous years, but now feel less stigma about responding about depression symptoms when filling out the survey. The survey has always been anonymous, but reporting bias can sometimes cause individuals to exaggerate or minimize their symptoms because of what they think researchers want their response to be or out of shame or embarrassment, among other reasons. However, the data suggests that youths may be experiencing more symptoms of depression and that the rate of increase is quite high. Now nearly a quarter of all individuals that were female and of age 12-17 reported experiencing symptoms of depression. This warrants further investigation to see if this is a product of more reporting or if indeed American females are truly more depressed. Furthermore,if they are indeed more depressed, investigation about why young females are more depressed is also of critical importance. One important limitation is that the data does not include subgroup intersections, such as rates of major depressive episodes among females of various ethnic backgrounds. Considering the very steep increase in females, this warrants further investigation about which females are particularly vulnerable and why.

Homework


Ask students to scrape tables 11.5A and 11.5B from the website which contain data about the receipt of treatment among youths who reported having a severe episode. Ask students to create plots and perform chi-square tests to evaluate how groups compare over time.

Additional Information


Acknowledgements

We would like to acknowledge Tamar Mendelson for assisting in framing the major direction of the case study.

We would also like to acknowledge the Bloomberg American Health Initiative for funding this work.

LS0tCnRpdGxlOiAiT3BlbiBDYXNlIFN0dWRpZXMgOiBNZW50YWwgSGVhbHRoIG9mIEFtZXJpY2FuIFlvdXRoIgpjc3M6IHN0eWxlLmNzcwpvdXRwdXQ6CiAgaHRtbF9kb2N1bWVudDoKICAgIHNlbGZfY29udGFpbmVkOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgaGlnaGxpZ2h0OiB0YW5nbwogICAgbnVtYmVyX3NlY3Rpb25zOiBubwogICAgdGhlbWU6IGNvc21vCiAgICB0b2M6IHllcwogICAgdG9jX2Zsb2F0OiB5ZXMKICBwZGZfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwoKLS0tCjxzdHlsZT4KI1RPQyB7CiAgYmFja2dyb3VuZDogdXJsKCJodHRwczovL29wZW5jYXNlc3R1ZGllcy5naXRodWIuaW8vaW1nL2xvZ28uanBnIik7CiAgYmFja2dyb3VuZC1zaXplOiBjb250YWluOwogIHBhZGRpbmctdG9wOiAyNDBweCAhaW1wb3J0YW50OwogIGJhY2tncm91bmQtcmVwZWF0OiBuby1yZXBlYXQ7Cn0KPC9zdHlsZT4KCgoKYGBge3Igc2V0dXAsIGluY2x1ZGU9RkFMU0V9CmtuaXRyOjpvcHRzX2NodW5rJHNldChpbmNsdWRlID0gVFJVRSwgY29tbWVudCA9IE5BLCBlY2hvID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZyA9IEZBTFNFLCBjYWNoZSA9IEZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgZmlnLmFsaWduID0gImNlbnRlciIsIG91dC53aWR0aCA9ICc5MCUnKQpsaWJyYXJ5KGhlcmUpCmxpYnJhcnkoa25pdHIpCmxpYnJhcnkobWFnaWNrKSMgdG8gY3JlYXRlIGdpZgpgYGAKCiMjIyMgey5vdXRsaW5lIH0KYGBge3IsIGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoID0gIjgwMCBweCJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJtYWlucGxvdC5wbmciKSkKYGBgCgojIyMjCgojIyB7LmRpc2NsYWltZXJfYmxvY2t9CgoqKkRpc2NsYWltZXIqKjogVGhlIHB1cnBvc2Ugb2YgdGhlIFtPcGVuIENhc2UgU3R1ZGllc10oaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvKXt0YXJnZXQ9Il9ibGFuayJ9IHByb2plY3QgaXMgKip0byBkZW1vbnN0cmF0ZSB0aGUgdXNlIG9mIHZhcmlvdXMgZGF0YSBzY2llbmNlIG1ldGhvZHMsIHRvb2xzLCBhbmQgc29mdHdhcmUgaW4gdGhlIGNvbnRleHQgb2YgbWVzc3ksIHJlYWwtd29ybGQgZGF0YSoqLiBBIGdpdmVuIGNhc2Ugc3R1ZHkgZG9lcyBub3QgY292ZXIgYWxsIGFzcGVjdHMgb2YgdGhlIHJlc2VhcmNoIHByb2Nlc3MsIGlzIG5vdCBjbGFpbWluZyB0byBiZSB0aGUgbW9zdCBhcHByb3ByaWF0ZSB3YXkgdG8gYW5hbHl6ZSBhIGdpdmVuIGRhdGEgc2V0LCBhbmQgc2hvdWxkIG5vdCBiZSB1c2VkIGluIHRoZSBjb250ZXh0IG9mIG1ha2luZyBwb2xpY3kgZGVjaXNpb25zIHdpdGhvdXQgZXh0ZXJuYWwgY29uc3VsdGF0aW9uIGZyb20gc2NpZW50aWZpYyBleHBlcnRzLiAKCiMjIHsubGljZW5zZV9ibG9ja30KClRoaXMgd29yayBpcyBsaWNlbnNlZCB1bmRlciB0aGUgQ3JlYXRpdmUgQ29tbW9ucyBBdHRyaWJ1dGlvbi1Ob25Db21tZXJjaWFsIDMuMCBbKENDIEJZLU5DIDMuMCldKGh0dHBzOi8vY3JlYXRpdmVjb21tb25zLm9yZy9saWNlbnNlcy9ieS1uYy8zLjAvdXMvKXt0YXJnZXQ9Il9ibGFuayJ9ICBVbml0ZWQgU3RhdGVzIExpY2Vuc2UuCgojIyB7LnJlZmVyZW5jZV9ibG9ja30KClRvIGNpdGUgdGhpcyBjYXNlIHN0dWR5IHBsZWFzZSB1c2U6CgpXcmlnaHQsIENhcnJpZSwgYW5kIE9udGl2ZXJvcywgTWljaGFlbCBhbmQgSmFnZXIsIExlYWggYW5kIFRhdWIsIE1hcmdhcmV0IGFuZCBIaWNrcywgU3RlcGhhbmllLiAoMjAyMCkuIGh0dHBzOi8vZ2l0aHViLmNvbS9vcGVuY2FzZXN0dWRpZXMvb2NzLXlvdXRoLW1lbnRhbC1oZWFsdGgtY2FzZS1zdHVkeS4gTWVudGFsIEhlYWx0aCBvZiBBbWVyaWNhbiBZb3V0aCAoVmVyc2lvbiB2MS4wLjApLgoKCiMjICoqTW90aXZhdGlvbioqCioqKiAKClJhdGVzIG9mIGRlcHJlc3Npb24gYXBwZWFyIHRvIGhhdmUgYmVlbiBpbmNyZWFzaW5nIGFtb25nIEFtZXJpY2FuIHlvdXRocyBzaW5jZSBhcm91bmQgMjAxMCBhY2NvcmRpbmcgdG8gYSByZWNlbnQgW3JlcG9ydF0oaHR0cHM6Ly9jb250ZW50LmFwYS5vcmcvcmVjb3JkLzIwMTktMTI1NzgtMDAxKXt0YXJnZXQ9Il9ibGFuayJ9LiBBIFtyZWNlbnQgc3R1ZHldKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMjQyODUzODIvKXt0YXJnZXQ9Il9ibGFuayJ9KSBhbHNvIHNob3dzIHRoYXQgeW91dGhzIGFwcGVhciB0byBiZSBzZWVraW5nIG1vcmUgY2FyZSBmcm9tIG1lbnRhbCBoZWFsdGggc2VydmljZXMuCgoKClRoaXMgY2FzZSBzdHVkeSB3aWxsIGV4cGxvcmUgaG93IHJhdGVzIG9mIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZXMgaGF2ZSBjaGFuZ2VkIHNpbmNlIHRoZSBlYXJseSAyMDAwcy4gQXMgd2VsbCBhcyBob3cgcmF0ZXMgb2YgdHJlYXRtZW50IGZvciBkZXByZXNzaW9uIG9mIHlvdXRocyBoYXZlIGNoYW5nZWQgb3ZlciB0aW1lLgoKCmBgYHtyLGVjaG8gPSBGQUxTRSwgb3V0LndpZHRoPSI0MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiay1taXRjaC1ob2RnZS1JcVNhRzl6djJlMC11bnNwbGFzaC5qcGciKSkKYGBgCjxzcGFuPlBob3RvIGJ5IDxhIGhyZWY9Imh0dHBzOi8vdW5zcGxhc2guY29tL0BrbWl0Y2hob2RnZT91dG1fc291cmNlPXVuc3BsYXNoJmFtcDt1dG1fbWVkaXVtPXJlZmVycmFsJmFtcDt1dG1fY29udGVudD1jcmVkaXRDb3B5VGV4dCI+Sy4gTWl0Y2ggSG9kZ2U8L2E+IG9uIDxhIGhyZWY9Imh0dHBzOi8vdW5zcGxhc2guY29tL3MvcGhvdG9zL2RlcHJlc3Npb24/dXRtX3NvdXJjZT11bnNwbGFzaCZhbXA7dXRtX21lZGl1bT1yZWZlcnJhbCZhbXA7dXRtX2NvbnRlbnQ9Y3JlZGl0Q29weVRleHQiPlVuc3BsYXNoPC9hPjwvc3Bhbj4gIAoKClRoZSBtYWpvciBzeW1wdG9tcyBvZiBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSBpbmNsdWRlOiAgIAoKKipTKipsZWVwIGRpc29yZGVyIChpbmNyZWFzZWQgb3IgZGVjcmVhc2VkKSAgCioqSSoqbnRlcmVzdCBkZWZpY2l0IChhbmhlZG9uaWEpICAKKipHKip1aWx0ICh3b3J0aGxlc3NuZXNzLCBob3BlbGVzc25lc3MsIHJlZ3JldCkgIAoqKkUqKm5lcmd5IGRlZmljaXQgIAoqKkMqKm9uY2VudHJhdGlvbiBkZWZpY2l0ICAKKipBKipwcGV0aXRlIGRpc29yZGVyIChpbmNyZWFzZWQgb3IgZGVjcmVhc2VkKSAgCioqUCoqc3ljaG9tb3RvciByZXRhcmRhdGlvbiBvciBhZ2l0YXRpb24gIAoqKlMqKnVpY2lkYWxpdHkgIAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3Lmljc2kub3JnL2d1aWRlbGluZS9kZXByZXNzaW9uL2RpYWdub3NlLWFuZC1jaGFyYWN0ZXJpemUtbWFqb3ItZGVwcmVzc2lvbi1wZXJzaXN0ZW50LWRlcHJlc3NpdmUtZGlzb3JkZXItd2l0aC1jbGluaWNhbC1pbnRlcnZpZXcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKCgpgYGB7ciwgZWNobyA9IEZBTFNFLCBvdXQud2lkdGg9IjgwJSJ9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJkZXByZXNzaW9uLXN5bXB0b21zLWFuZC10cmVhdG1lbnQtNzY4eDc2OC5qcGciKSkKYGBgCgojIyMjIFtbc291cmNlXV0oaHR0cHM6Ly9uZXdtaWxmb3JkY291bnNlbGluZ2NlbnRlci5jb20vZGVwcmVzc2lvbi0yLyl7dGFyZ2V0PSJfYmxhbmsifSAgCgo8ZGV0YWlscz4gPHN1bW1hcnk+IENsaWNrIGhlcmUgdG8gc2VlIHRoZSBkaWFnbm9zdGljIHJlcXVpcmVtZW50cyBmb3IgYSBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUgYWNjb3JkaW5nIHRvIHRoZSBbRFNNIDVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0RTTS01KXt0YXJnZXQ9Il9ibGFuayJ9PC9zdW1tYXJ5PiAgICAKCkZpdmUgb3IgbW9yZSBvZiB0aGUgZm9sbG93aW5nIHN5bXB0b21zIGhhdmUgYmVlbiBwcmVzZW50IGFuZCBkb2N1bWVudGVkIGR1cmluZyB0aGUgc2FtZSB0d28td2VlayBwZXJpb2QgYW5kIHJlcHJlc2VudCBhIGNoYW5nZSBmcm9tIHByZXZpb3VzIGZ1bmN0aW9uaW5nOyBhdCBsZWFzdCBvbmUgb2YgdGhlIHN5bXB0b21zIGlzIGVpdGhlciAoMSkgZGVwcmVzc2VkIG1vb2Qgb3IgKDIpIGxvc3Mgb2YgaW50ZXJlc3Qgb3IgcGxlYXN1cmUuICAKCk5vdGU6IERvIG5vdCBpbmNsdWRlIHN5bXB0b21zIHRoYXQgYXJlIGNsZWFybHkgYXR0cmlidXRhYmxlIHRvIGFub3RoZXIgbWVkaWNhbCBjb25kaXRpb24uICAKCjEpIERlcHJlc3NlZCBtb29kIG1vc3Qgb2YgdGhlIGRheSwgbmVhcmx5IGV2ZXJ5IGRheSwgYXMgaW5kaWNhdGVkIGJ5IGVpdGhlciBzdWJqZWN0aXZlIHJlcG9ydCAoZS5nLiwgZmVlbHMgc2FkLCBlbXB0eSwgaG9wZWxlc3MpIG9yIG9ic2VydmF0aW9uIG1hZGUgYnkgb3RoZXJzIChlLmcuLCBhcHBlYXJzIHRlYXJmdWwpICAKCjIpIE1hcmtlZGx5IGRpbWluaXNoZWQgaW50ZXJlc3Qgb3IgcGxlYXN1cmUgaW4gYWxsLCBvciBhbG1vc3QgYWxsLCBhY3Rpdml0aWVzIG1vc3Qgb2YgdGhlIGRheSwgbmVhcmx5IGV2ZXJ5IGRheSAoYXMgaW5kaWNhdGVkIGJ5IGVpdGhlciBzdWJqZWN0aXZlIGFjY291bnQgb3Igb2JzZXJ2YXRpb24pICAKCjMpIFNpZ25pZmljYW50IHdlaWdodCBsb3NzIHdoZW4gbm90IGRpZXRpbmcgb3Igd2VpZ2h0IGdhaW4gKGUuZy4sIGEgY2hhbmdlIG9mIG1vcmUgdGhhbiA1JSBvZiBib2R5IHdlaWdodCBpbiBhIG1vbnRoKSwgb3IgZGVjcmVhc2Ugb3IgaW5jcmVhc2UgaW4gYXBwZXRpdGUgbmVhcmx5IGV2ZXJ5IGRheSAgCgo0KSBJbnNvbW5pYSBvciBoeXBlcnNvbW5pYSBuZWFybHkgZXZlcnkgZGF5ICAKCjUpIFBzeWNob21vdG9yIGFnaXRhdGlvbiBvciByZXRhcmRhdGlvbiBuZWFybHkgZXZlcnkgZGF5IChvYnNlcnZhYmxlIGJ5IG90aGVycywgbm90IG1lcmVseSBzdWJqZWN0aXZlIGZlZWxpbmdzIG9mIHJlc3RsZXNzbmVzcyBvciBiZWluZyBzbG93ZWQgZG93bikgIAoKNikgRmF0aWd1ZSBvciBsb3NzIG9mIGVuZXJneSBuZWFybHkgZXZlcnkgZGF5ICAKCjcpIEZlZWxpbmdzIG9mIHdvcnRobGVzc25lc3Mgb3IgZXhjZXNzaXZlIG9yIGluYXBwcm9wcmlhdGUgZ3VpbHQgKHdoaWNoIG1heSBiZSBkZWx1c2lvbmFsKSBuZWFybHkgZXZlcnkgZGF5IChub3QgbWVyZWx5IHNlbGYtcmVwcm9hY2ggb3IgZ3VpbHQgYWJvdXQgYmVpbmcgc2ljaykgIAoKOCkgRGltaW5pc2hlZCBhYmlsaXR5IHRvIHRoaW5rIG9yIGNvbmNlbnRyYXRlLCBvciBpbmRlY2lzaXZlbmVzcywgbmVhcmx5IGV2ZXJ5IGRheSAoZWl0aGVyIGJ5IHN1YmplY3RpdmUgYWNjb3VudCBvciBhcyBvYnNlcnZlZCBieSBvdGhlcnMpICAKCjkpIFJlY3VycmVudCB0aG91Z2h0cyBvZiBkZWF0aCAobm90IGp1c3QgZmVhciBvZiBkeWluZyksIHJlY3VycmVudCBzdWljaWRhbCBpZGVhdGlvbiB3aXRob3V0IGEgc3BlY2lmaWMgcGxhbiwgb3IgYSBzdWljaWRlIGF0dGVtcHQgb3IgYSBzcGVjaWZpYyBwbGFuIGZvciBjb21taXR0aW5nIHN1aWNpZGUgIAoKQi4gVGhlIHN5bXB0b21zIGRvIG5vdCBtZWV0IGNyaXRlcmlhIGZvciBhIG1peGVkIGVwaXNvZGUuICAKCkMuIFRoZSBlcGlzb2RlIGlzIG5vdCBhdHRyaWJ1dGFibGUgdG8gdGhlIHBoeXNpb2xvZ2ljYWwgZWZmZWN0cyBvZiBhIHN1YnN0YW5jZSBvciB0byBhbm90aGVyIG1lZGljYWwgY29uZGl0aW9uLiAgCgpOb3RlOiBDcml0ZXJpYSBBLUMgcmVwcmVzZW50IGEgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlLiAgCgpOb3RlOiBSZXNwb25zZXMgdG8gYSBzaWduaWZpY2FudCBsb3NzIChlLmcuLCBiZXJlYXZlbWVudCwgZmluYW5jaWFsIHJ1aW4sIGxvc3NlcyBmcm9tIGEgbmF0dXJhbCBkaXNhc3RlciwgYSBzZXJpb3VzIG1lZGljYWwgaWxsbmVzcyBvciBkaXNhYmlsaXR5KSBtYXkgaW5jbHVkZSBmZWVsaW5ncyBvZiBpbnRlbnNlIHNhZG5lc3MsIHJ1bWluYXRpb24gYWJvdXQgdGhlIGxvc3MsIGluc29tbmlhLCBwb29yIGFwcGV0aXRlIGFuZCB3ZWlnaHQgbG9zcyBub3RlZCBpbiBDcml0ZXJpb24gQSwgd2hpY2ggbWF5IHJlc2VtYmxlIGEgZGVwcmVzc2l2ZSBlcGlzb2RlLiBBbHRob3VnaCBzdWNoIHN5bXB0b21zIG1heSBiZSB1bmRlcnN0YW5kYWJsZSBvciBjb25zaWRlcmVkIGFwcHJvcHJpYXRlIHRvIHRoZSBsb3NzLCB0aGUgcHJlc2VuY2Ugb2YgYSBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUgaW4gYWRkaXRpb24gdG8gdGhlIG5vcm1hbCByZXNwb25zZSB0byBhIHNpZ25pZmljYW50IGxvc3Mgc2hvdWxkIGFsc28gYmUgY2FyZWZ1bGx5IGNvbnNpZGVyZWQuIFRoaXMgZGVjaXNpb24gaW5ldml0YWJseSByZXF1aXJlcyB0aGUgZXhlcmNpc2Ugb2YgY2xpbmljYWwganVkZ21lbnQgYmFzZWQgb24gdGhlIGluZGl2aWR1YWzigJlzIGhpc3Rvcnkgb2YgYW5kIHRoZSBjdWx0dXJhbCBub3JtcyBmb3IgdGhlIGV4cHJlc3Npb24gb2YgZGlzdHJlc3MgaW4gdGhlIGNvbnRleHQgb2YgbG9zcy4gIAoKRC4gVGhlIG9jY3VycmVuY2Ugb2YgdGhlIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSBpcyBub3QgYmV0dGVyIGV4cGxhaW5lZCBieSBzY2hpem9hZmZlY3RpdmUgZGlzb3JkZXIsIHNjaGl6b3BocmVuaWEsIHNjaGl6b3BocmVuaWZvcm0gZGlzb3JkZXIsIGRlbHVzaW9uYWwgZGlzb3JkZXIsIG9yIG90aGVyIHNwZWNpZmllZCBhbmQgdW5zcGVjaWZpZWQgc2NoaXpvcGhyZW5pYSBzcGVjdHJ1bSBhbmQgb3RoZXIgcHN5Y2hvdGljIGRpc29yZGVycy4gIAoKRS4gVGhlcmUgaGFzIG5ldmVyIGJlZW4gYSBtYW5pYyBlcGlzb2RlIG9yIGEgaHlwb21hbmljIGVwaXNvZGUuICAKCk5vdGU6IFRoaXMgZXhjbHVzaW9uIGRvZXMgbm90IGFwcGx5IGlmIGFsbCBvZiB0aGUgbWFuaWMtbGlrZSBvciBoeXBvbWFuaWMtbGlrZSBlcGlzb2RlcyBhcmUgc3Vic3RhbmNlLWluZHVjZWQgb3IgYXJlIGF0dHJpYnV0YWJsZSB0byB0aGUgcGh5c2lvbG9naWNhbCBlZmZlY3RzIG9mIGFub3RoZXIgbWVkaWNhbCBjb25kaXRpb24uICAKCjwvZGV0YWlscz4gIAogIAogICAgCiAgClRoaXMgY2FzZSBzdHVkeSBpcyBtb3RpdmF0ZWQgYnkgdGhlIGZvbGxvd2luZyB0d28gYXJ0aWNsZXM6ICAKICAKCiMjIyMgey5yZWZlcmVuY2VfYmxvY2t9CgpUd2VuZ2UgSk0sIENvb3BlciBBQiwgSm9pbmVyIFRFLCBEdWZmeSBNRSwgQmluYXUgU0cuIEFnZSwgcGVyaW9kLCBhbmQgY29ob3J0IHRyZW5kcyBpbiBtb29kIGRpc29yZGVyIGluZGljYXRvcnMgYW5kIHN1aWNpZGUtcmVsYXRlZCBvdXRjb21lcyBpbiBhIG5hdGlvbmFsbHkgcmVwcmVzZW50YXRpdmUgZGF0YXNldCwgMjAwNS0yMDE3LiAqSiBBYm5vcm0gUHN5Y2hvbCouMTI4LDMgKDIwMTkpOjE4NS0xOTkuIGRvaToxMC4xMDM3L2FibjAwMDA0MTAKCgpPbGZzb24sIE0uLCBCbGFuY28sIEMuLCBXYW5nLCBTLiwgTGFqZSwgRy4gJiBDb3JyZWxsLCBDLiBVLiBOYXRpb25hbCBUcmVuZHMgaW4gdGhlIE1lbnRhbCBIZWFsdGggQ2FyZSBvZiBDaGlsZHJlbiwgQWRvbGVzY2VudHMsIGFuZCBBZHVsdHMgYnkgT2ZmaWNlLUJhc2VkIFBoeXNpY2lhbnMuICpKQU1BIFBzeWNoaWF0cnkqLiA3MSwgODEgKDIwMTQpOjgxLTkwLiBkb2k6IDEwLjEwMDEvamFtYXBzeWNoaWF0cnkuMjAxMy4zMDc0LgoKIyMjIwoKVGhlIG1haW4gZmluZGluZ3Mgb2YgdGhlIGZpcnN0IFthcnRpY2xlXShodHRwczovL2NvbnRlbnQuYXBhLm9yZy9yZWNvcmQvMjAxOS0xMjU3OC0wMDEpe3RhcmdldD0iX2JsYW5rIn0gYXJlOgoKPiBSYXRlcyBvZiBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUgaW4gdGhlIGxhc3QgeWVhciBpbmNyZWFzZWQgNTIlIDIwMDXigJMyMDE3IChmcm9tIDguNyUgdG8gMTMuMiUpIGFtb25nIGFkb2xlc2NlbnRzIGFnZWQgMTIgdG8gMTcgYW5kIDYzJSAyMDA54oCTMjAxNyAoZnJvbSA4LjElIHRvIDEzLjIlKSBhbW9uZyB5b3VuZyBhZHVsdHMgMTjigJMyNS4gCgo+IFNlcmlvdXMgcHN5Y2hvbG9naWNhbCBkaXN0cmVzcyBpbiB0aGUgbGFzdCBtb250aCBhbmQgc3VpY2lkZS1yZWxhdGVkIG91dGNvbWVzIChzdWljaWRhbCBpZGVhdGlvbiwgcGxhbnMsIGF0dGVtcHRzLCBhbmQgZGVhdGhzIGJ5IHN1aWNpZGUpIGluIHRoZSBsYXN0IHllYXIgYWxzbyBpbmNyZWFzZWQgYW1vbmcgeW91bmcgYWR1bHRzIDE44oCTMjUgZnJvbSAyMDA44oCTMjAxNyAod2l0aCBhIDcxJSBpbmNyZWFzZSBpbiBzZXJpb3VzIHBzeWNob2xvZ2ljYWwgZGlzdHJlc3MpLCB3aXRoIGxlc3MgY29uc2lzdGVudCBhbmQgd2Vha2VyIGluY3JlYXNlcyBhbW9uZyBhZHVsdHMgYWdlcyAyNiBhbmQgb3Zlci4gCgo+IEN1bHR1cmFsIHRyZW5kcyBjb250cmlidXRpbmcgdG8gYW4gaW5jcmVhc2UgaW4gbW9vZCBkaXNvcmRlcnMgYW5kIHN1aWNpZGFsIHRob3VnaHRzIGFuZCBiZWhhdmlvcnMgc2luY2UgdGhlIG1pZC0yMDAwcywgaW5jbHVkaW5nIHRoZSByaXNlIG9mIGVsZWN0cm9uaWMgY29tbXVuaWNhdGlvbiBhbmQgZGlnaXRhbCBtZWRpYSBhbmQgZGVjbGluZXMgaW4gc2xlZXAgZHVyYXRpb24sIG1heSBoYXZlIGhhZCBhIGxhcmdlciBpbXBhY3Qgb24geW91bmdlciBwZW9wbGUsIGNyZWF0aW5nIGEgY29ob3J0IGVmZmVjdC4KCldoaWxlIHRoZSBtYWluIGZpbmRpbmdzIG9mIHRoZSBzZWNvbmQgW2FydGljbGVdKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMjQyODUzODIvKXt0YXJnZXQ9Il9ibGFuayJ9IGFyZToKCj5Db21wYXJlZCB3aXRoIGFkdWx0IG1lbnRhbCBoZWFsdGggY2FyZSwgdGhlIG1lbnRhbCBoZWFsdGgKY2FyZSBvZiB5b3VuZyBwZW9wbGUgaGFzIGluY3JlYXNlZCBtb3JlIHJhcGlkbHkuCgo+QmV0d2VlbiAxOTk1LTE5OTggYW5kIDIwMDctMjAxMCwgdmlzaXRzIHJlc3VsdGluZyBpbiBtZW50YWwgZGlzb3JkZXIgZGlhZ25vc2VzCnBlciAxMDAgcG9wdWxhdGlvbiBpbmNyZWFzZWQgc2lnbmlmaWNhbnRseSBmYXN0ZXIgZm9yIHlvdXRocyAoZnJvbSA3Ljc4IHRvIDE1LjMwIHZpc2l0cykgdGhhbiBmb3IKYWR1bHRzIChmcm9tIDIzLjIzIHRvIDI4LjQ4IHZpc2l0cykgKGludGVyYWN0aW9uOiBQIDwgLjAwMSkuIAoKPlBzeWNoaWF0cmlzdCB2aXNpdHMgYWxzbyBpbmNyZWFzZWQKc2lnbmlmaWNhbnRseSBmYXN0ZXIgZm9yIHlvdXRocyAoZnJvbSAyLjg2IHRvIDUuNzEgdmlzaXRzKS4KCgpBZ2FpbiB3aGlsZSBkZXByZXNzaW9uIGFwcGVhciB0byBiZSBvbiB0aGUgcmlzZSBmb3IgeW91dGhzLCB5b3V0aHMgYWxzbyBhcHBlYXIgdG8gYmUgc2Vla2luZyBtb3JlIG1lbnRhbCBoZWFsdGggY2FyZS4KCkluIHRoaXMgY2FzZSBzdHVkeSB3ZSB3aWxsIGJlIHVzaW5nIGRhdGEgZnJvbSB0aGUgW05hdGlvbmFsIFN1cnZleSBvbiBEcnVnIFVzZSBhbmQgSGVhbHRoIChOU0RVSCldKGh0dHBzOi8vbnNkdWh3ZWIucnRpLm9yZy9yZXNwd2ViL2hvbWVwYWdlLmNmbSl7dGFyZ2V0PSJfYmxhbmsifSByZWxhdGVkIHRvIHRyZWF0bWVudCBhbmQgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIHJhdGUgdG8gZXhwbG9yZSBob3cgdGhpcyBoYXZlIGNoYW5nZWQgb3ZlciB0aW1lIGFuZCBob3cgZGlmZmVyZW50IGdyb3VwcyBjb21wYXJlLiBUaGlzIGRhdGEgd2FzIGFsc28gdXNlZCBpbiB0aGUgZmlyc3QgcmVmZXJlbmNlZCBhcnRpY2xlLiAgCgoKIyMgKipNYWluIFF1ZXN0aW9ucyoqCioqKiAKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb25zOiA8L3U+PC9iPgoKMSkgSG93IGhhdmUgZGVwcmVzc2lvbiByYXRlcyBpbiBBbWVyaWNhbiB5b3V0aCBjaGFuZ2VkIHNpbmNlIDIwMDQsIGFjY29yZGluZyB0byB0aGUgTlNEVUggZGF0YT8gSG93IGhhdmUgcmF0ZXMgZGlmZmVyZWQgYmV0d2VlbiBkaWZmZXJlbnQgeW91dGggc3ViZ3JvdXBzIChhZ2UsIGdlbmRlciwgZXRobmljaXR5KT8KMikgRG8gbWVudGFsIGhlYWx0aCBzZXJ2aWNlcyBhcHBlYXIgdG8gYmUgcmVhY2hpbmcgbW9yZSB5b3V0aHM/IEFnYWluLCBob3cgaGF2ZSByYXRlcyBkaWZmZXJlZCBiZXR3ZWVuIGRpZmZlcmVudCB5b3V0aCBzdWJncm91cHMgKGFnZSwgZ2VuZGVyLCBldGhuaWNpdHkpPwoKCiMjIyMKCiMjICoqTGVhcm5pbmcgT2JqZWN0aXZlcyoqIAoqKiogCgo8dT4qKlN0YXRpc3RpY2FsIExlYXJuaW5nIE9iamVjdGl2ZXM6Kio8L3U+IAoKMS4gRGVmaW5lIGFuZCBjcmVhdGUgYSBjb250aW5nZW5jeSB0YWJsZS4KMi4gSW1wbGVtZW50YXRpb24gb2YgYSBjaGktc3F1YXJlZCB0ZXN0IGZvciBpbmRlcGVuZGVuY2UuCjMuIEludGVycHJldGF0aW9uIG9mIGEgY2hpLXNxdWFyZWQgdGVzdCBmb3IgaW5kZXBlbmRlbmNlLgoKPHU+KipEYXRhIHNjaWVuY2UgTGVhcm5pbmcgT2JqZWN0aXZlczoqKjwvdT4KCjEuIFNjcmFwZSBkYXRhIGRpcmVjdGx5IGZyb20gYSB3ZWJzaXRlIChgcnZlc3RgKS4KMi4gU3Vic2V0IGFuZCBmaWx0ZXIgZGF0YSAoYGRwbHlyYCkuCjMuIFdyaXRlIGZ1bmN0aW9ucyB0byB3cmFuZ2xlIGRhdGEgcmVwZXRpdGl2ZWx5Lgo0LiBXb3JrIHdpdGggY2hhcmFjdGVyIHN0cmluZ3MgKGBzdHJpbmdyYCkuCjUuIFJlc2hhcGUgZGF0YSBpbnRvIGRpZmZlcmVudCBmb3JtYXRzIChgdGlkeXJgKS4KNi4gRGF0YSB2aXN1YWxpemF0aW9ucyAoYGdncGxvdDJgKSB3aXRoIGxhYmVscyAoYGRpcmVjdGxhYmVsc2ApIGFuZCBmYWNldHMgZm9yIGRpZmZlcmVudCBncm91cHMuCgoKSW4gdGhpcyBjYXNlIHN0dWR5LCB3ZSB3aWxsIGVzcGVjaWFsbHkgZm9jdXMgb24gdXNpbmcgcGFja2FnZXMgYW5kIGZ1bmN0aW9ucyBmcm9tIHRoZSBbYFRpZHl2ZXJzZWBdKGh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9LCBzdWNoIGFzIFtgcnZlc3RgXShodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL3J2ZXN0KXt0YXJnZXQ9Il9ibGFuayJ9LiBUaGUgdGlkeXZlcnNlIGlzIGEgbGlicmFyeSBvZiBwYWNrYWdlcyBjcmVhdGVkIGJ5IFJTdHVkaW8uIFdoaWxlIHNvbWUgc3R1ZGVudHMgbWF5IGJlIGZhbWlsaWFyIHdpdGggcHJldmlvdXMgUiBwcm9ncmFtbWluZyBwYWNrYWdlcywgdGhlc2UgcGFja2FnZXMgbWFrZSBkYXRhIHNjaWVuY2UgaW4gUiBlc3BlY2lhbGx5IGVmZmljaWVudC4KCmBgYHtyLCBvdXQud2lkdGggPSAiMjAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3RpZHl2ZXJzZS50aWR5dmVyc2Uub3JnL2xvZ28ucG5nIikKYGBgCgoqKiogCgpXZSB3aWxsIGJlZ2luIGJ5IGxvYWRpbmcgdGhlIHBhY2thZ2VzIHRoYXQgd2Ugd2lsbCBuZWVkOgoKYGBge3J9CmxpYnJhcnkoaGVyZSkKbGlicmFyeShydmVzdCkKbGlicmFyeShkcGx5cikKbGlicmFyeShtYWdyaXR0cikKbGlicmFyeShzdHJpbmdyKQpsaWJyYXJ5KHRpZHlyKQpsaWJyYXJ5KHRpYmJsZSkKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGRpcmVjdGxhYmVscykKbGlicmFyeShmb3JjYXRzKQpsaWJyYXJ5KGNvd3Bsb3QpCmBgYAoKCgogUGFja2FnZSAgIHwgVXNlICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIAotLS0tLS0tLS0tIHwtLS0tLS0tLS0tLS0tCltoZXJlXShodHRwczovL2dpdGh1Yi5jb20vamVubnliYy9oZXJlX2hlcmUpe3RhcmdldD0iX2JsYW5rIn0gICAgICAgfCB0byBlYXNpbHkgbG9hZCBhbmQgc2F2ZSBkYXRhICAKW3J2ZXN0XShodHRwczovL2dpdGh1Yi5jb20vdGlkeXZlcnNlL3J2ZXN0KXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzY3JhcGUgd2ViIHBhZ2VzICAKW2RwbHlyXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzY3JhcGUgd2ViIHBhZ2VzICAKW21hZ3JpdHRyXShodHRwczovL21hZ3JpdHRyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBzY3JhcGUgd2ViIHBhZ2VzICAKW3N0cmluZ3JdKGh0dHBzOi8vc3RyaW5nci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gbWFuaXB1bGF0ZSBzdHJpbmdzICAKW3RpZHlyXShodHRwczovL3RpZHlyLnRpZHl2ZXJzZS5vcmcvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgfCB0byBjaGFuZ2UgdGhlIHNoYXBlIG9yIGZvcm1hdCBvZiB0aWJibGVzIHRvIHdpZGUgYW5kIGxvbmcgIApbdGliYmxlXShodHRwczovL3RpYmJsZS50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gY3JlYXRlIHRpYmJsZXMgYW5kIGNvbnZlcnQgdmFsdWVzIG9mIGEgY29sdW1uIHRvIHJvdyBuYW1lcyAgCltnZ3Bsb3QyXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGNyZWF0ZSBwbG90cyAgCltkaXJlY3RsYWJlbHNdKGh0dHA6Ly9kaXJlY3RsYWJlbHMuci1mb3JnZS5yLXByb2plY3Qub3JnL2RvY3MvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gYWRkIGxhYmVscyBkaXJlY3RseSB0byBsaW5lcyBpbiBwbG90cyAgCltmb3JjYXRzXShodHRwczovL2ZvcmNhdHMudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHJlb3JkZXIgZmFjdG9yIGZvciBwbG90ICAKW2Nvd3Bsb3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jb3dwbG90L3ZpZ25ldHRlcy9pbnRyb2R1Y3Rpb24uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gY29tYmluZSBwbG90cyB0b2dldGhlciAgCgoKVGhlIGZpcnN0IHRpbWUgd2UgdXNlIGEgZnVuY3Rpb24sIHdlIHdpbGwgdXNlIHRoZSBgOjpgIHRvIGluZGljYXRlIHdoaWNoIHBhY2thZ2Ugd2UgYXJlIHVzaW5nLiBVbmxlc3Mgd2UgaGF2ZSBvdmVybGFwcGluZyBmdW5jdGlvbiBuYW1lcywgdGhpcyBpcyBub3QgbmVjZXNzYXJ5LCBidXQgd2Ugd2lsbCBpbmNsdWRlIGl0IGhlcmUgdG8gYmUgaW5mb3JtYXRpdmUgYWJvdXQgd2hlcmUgdGhlIGZ1bmN0aW9ucyB3ZSB3aWxsIHVzZSBjb21lIGZyb20uCgojIyAqKkNvbnRleHQqKgoqKiogCgpBY2NvcmRpbmcgdG8gdGhlIENEQyB0aGUgcmF0ZSBvZiBzdWljaWRlIGhhcyBhbHNvIGluY3JlYXNlZCBmb3IgbW9zdCBhZ2UgZ3JvdXBzIGluIHRoZSBVbml0ZWQgU3RhdGVzIG92ZXIgdGhlIHBhc3QgZGVjYWRlIGFuZCBhIGhhbGYuCgpgYGB7ciwgb3V0LndpZHRoID0gIjgwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2ltYWdlcy9kYXRhYnJpZWZzLzMwMS0zNTAvZGIzMDlfZmlnMS5wbmciKQpgYGAKCiMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvcHJvZHVjdHMvZGF0YWJyaWVmcy9kYjMwOS5odG0pe3RhcmdldD0iX2JsYW5rIn0KCgpXaGlsZSBzdWljaWRlIGRvZXMgYXBwZWFyIHRvIGJlIGluY3JlYXNpbmcgYW1vbmcgeW91dGhzIGl0IGFsc28gYXBwZWFycyB0byBiZSBpbmNyZWFzaW5nIGFtb25nIG1pZGRsZSBhZ2VkIGFkdWx0cyBmb3IgYm90aCBmZW1hbGVzIGFuZCBtYWxlcy4gCgpgYGB7ciwgb3V0LndpZHRoID0gIjgwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL2ltYWdlcy9kYXRhYnJpZWZzLzMwMS0zNTAvZGIzMDlfZmlnMi5wbmciKQpgYGAKCiMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvcHJvZHVjdHMvZGF0YWJyaWVmcy9kYjMwOS5odG0pe3RhcmdldD0iX2JsYW5rIn0KCgoKCmBgYHtyLCBvdXQud2lkdGggPSAiODAlIiwgZWNobyA9IEZBTFNFLCBmaWcuYWxpZ24gPSJjZW50ZXIifQppbmNsdWRlX2dyYXBoaWNzKCJodHRwczovL3d3dy5jZGMuZ292L25jaHMvaW1hZ2VzL2RhdGFicmllZnMvMzAxLTM1MC9kYjMwOV9maWczLnBuZyIpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9wcm9kdWN0cy9kYXRhYnJpZWZzL2RiMzA5Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifQoKCkFjY29yZGluZyB0byB0aGUgW0NEQ10oaHR0cHM6Ly93d3cuY2RjLmdvdi9uY2hzL3Byb2R1Y3RzL2RhdGFicmllZnMvZGIzMDkuaHRtKXt0YXJnZXQ9Il9ibGFuayJ9OgoKPiBTaW5jZSAyMDA4LCBzdWljaWRlIGhhcyByYW5rZWQgYXMgdGhlIDEwdGggbGVhZGluZyBjYXVzZSBvZiBkZWF0aCBmb3IgYWxsIGFnZXMgaW4gdGhlIFVuaXRlZCBTdGF0ZXMuIEluIDIwMTYsIHN1aWNpZGUgYmVjYW1lIHRoZSAqKnNlY29uZCBsZWFkaW5nIGNhdXNlIG9mIGRlYXRoKiogYW1vbmcgdGhvc2UgYWdlZCAqKjEw4oCTMzQqKiBhbmQgdGhlIGZvdXJ0aCBsZWFkaW5nIGNhdXNlIGFtb25nIHRob3NlIGFnZWQgMzXigJM1NC4KCgoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJtb3J0YWxpdHkucG5nIikpCmBgYAoKIyMjIyBbW3NvdXJjZV1dKGh0dHBzOi8vd3d3LmNkYy5nb3YvbmNocy9kYXRhL2RhdGFicmllZnMvZGIyOTMucGRmKXt0YXJnZXQ9Il9ibGFuayJ9ICAgCgogIAoKKipTbyBhbHRob3VnaCBzdWljaWRlIGlzIG9uIHRoZSByaXNlIGZvciBtb3N0IGFnZSBncm91cHMsIHN1aWNpZGUgaXMgb25lIG9mIHRoZSB0b3AgKnR3byogY29udHJpYnV0b3JzIHRvIGRlYXRoIGZvciB5b3V0aHMuKiogICAKClRodXMgdGhpcyB3YXJyYW50cyBmdXJ0aGVyIGV4YW1pbmF0aW9uIG9mIHRoZSBtZW50YWwgaGVhbHRoIG9mIEFtZXJpY2FuIHlvdXRocy4gIAoKCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJtb3J0YWxpdHlfYWdlLnBuZyIpKQpgYGAKCiMjIyMgW1tzb3VyY2VdXShodHRwczovL3d3dy5jZGMuZ292L25jaHMvZGF0YS9udnNyL252c3I2OC9udnNyNjhfMDYtNTA4LnBkZil7dGFyZ2V0PSJfYmxhbmsifQoKCgpIaXN0b3JpY2FsbHksIHN1aWNpZGUgcmF0ZXMgd2VyZSBtdWNoIGhpZ2hlciBiZWZvcmUgMTk1MCwgaG93ZXZlciwgd2UgYXJlIHNlZWluZyBhbiBpbmNyZWFzZSBpbiB0aGUgbGFzdCAyMCB5ZWFycy4KCmBgYHtyLCBlY2hvID0gRkFMU0UsIG91dC53aWR0aD0iODAwcHgifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCJzdWljaWRlLnBuZyIpKQpgYGAKCiMjIyMgW1tzb3VyY2VdXShodHRwczovL3RpbWUuY29tLzU2MDkxMjQvdXMtc3VpY2lkZS1yYXRlLWluY3JlYXNlLyl7dGFyZ2V0PSJfYmxhbmsifQoKCgpCZXNpZGVzIHRoZSBVUywgW290aGVyIGNvdW50cmllc10oaHR0cHM6Ly9hY2FkZW1pYy5vdXAuY29tL2lqZS9hcnRpY2xlLzQ4LzUvMTY1MC81MzY2MjEwKXt0YXJnZXQ9Il9ibGFuayJ9IGFyZSBhbHNvIGV4cGVyaWVuY2luZyBpbmNyZWFzZWQgcmF0ZXMgb2YgZGVwcmVzc2lvbiBpbiB5b3V0aHMuIFNlZSBbdGhpcyByZXBvcnRdKGh0dHBzOi8vYXBwcy53aG8uaW50L2lyaXMvYml0c3RyZWFtL2hhbmRsZS8xMDY2NS8yNTQ2MTAvV0hPLU1TRC1NRVItMjAxNy4yLWVuZy5wZGY7anNlc3Npb25pZD1FNDQzNjAwNTVERDgzRUFDNDcyQUE0MEMyODUzREJGQT9zZXF1ZW5jZT0xKXt0YXJnZXQ9Il9ibGFuayJ9IGZyb20gdGhlICBXb3JsZCBIZWFsdGggT3JnYW5pemF0aW9uIGFib3V0IHJhdGVzIG9mIGRlcHJlc3Npb24gaW4gb3RoZXIgY291bnRyaWVzLgoKU2VlIFtoZXJlXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUMzMzMwMTYxLyl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgYW4gaW50ZXJlc3RpbmcgZGlzY3Vzc2lvbiBhYm91dCB3aGF0IG1heSBiZSBjYXVzaW5nIGluY3JlYXNlZCBkZXByZXNzaW9uIHJhdGVzLiAKCgpBY2NvcmRpbmcgdG8gdGhlIFtOYXRpb25hbCBJbnN0aXR1dGUgb2YgTWVudGFsIEhlYWx0aCAoTklNSCldKGh0dHBzOi8vd3d3Lm5pbWgubmloLmdvdi9oZWFsdGgvcHVibGljYXRpb25zL3RlZW4tZGVwcmVzc2lvbi9pbmRleC5zaHRtbCl7dGFyZ2V0PSJfYmxhbmsifToKCgojIyMjIHsuZW1waGFzaXNfYmxvY2t9CgpJZiB5b3UgYXJlIGluIGNyaXNpcyBhbmQgbmVlZCBoZWxwLCBjYWxsIHRoaXMgdG9sbC1mcmVlIG51bWJlciBmb3IgdGhlICoqTmF0aW9uYWwgU3VpY2lkZSBQcmV2ZW50aW9uIExpZmVsaW5lIChOU1BMKSoqLCBhdmFpbGFibGUgMjQgaG91cnMgYSBkYXksIGV2ZXJ5IGRheTogKioxLTgwMC0yNzMtVEFMSyAoODI1NSkqKi4gVGhlIHNlcnZpY2UgaXMgYXZhaWxhYmxlIHRvIGV2ZXJ5b25lLiBUaGUgZGVhZiBhbmQgaGFyZCBvZiBoZWFyaW5nIGNhbiBjb250YWN0IHRoZSBMaWZlbGluZSB2aWEgVFRZIGF0IDEtODAwLTc5OS00ODg5LiBBbGwgY2FsbHMgYXJlIGNvbmZpZGVudGlhbC4gWW91IGNhbiBhbHNvIHZpc2l0IHRoZSBMaWZlbGluZeKAmXMgd2Vic2l0ZSBhdCBbd3d3LnN1aWNpZGVwcmV2ZW50aW9ubGlmZWxpbmUub3JnXSh3d3cuc3VpY2lkZXByZXZlbnRpb25saWZlbGluZS5vcmcpe3RhcmdldD0iX2JsYW5rIn0uCgpUaGUgKipDcmlzaXMgVGV4dCBMaW5lKiogaXMgYW5vdGhlciBmcmVlLCBjb25maWRlbnRpYWwgcmVzb3VyY2UgYXZhaWxhYmxlIDI0IGhvdXJzIGEgZGF5LCBzZXZlbiBkYXlzIGEgd2Vlay4gVGV4dCDigJxIT01F4oCdIHRvICoqNzQxNzQxKiogYW5kIGEgdHJhaW5lZCBjcmlzaXMgY291bnNlbG9yIHdpbGwgcmVzcG9uZCB0byB5b3Ugd2l0aCBzdXBwb3J0IGFuZCBpbmZvcm1hdGlvbiBvdmVyIHRleHQgbWVzc2FnZS4gVmlzaXQgW3d3dy5jcmlzaXN0ZXh0bGluZS5vcmddKHd3dy5jcmlzaXN0ZXh0bGluZS5vcmcpe3RhcmdldD0iX2JsYW5rIn0uCgojIyMjCgpBbHNvIHNlZSBbaGVyZV0oaHR0cHM6Ly93d3cubWhhbmF0aW9uYWwub3JnL2RlcHJlc3Npb24tdGVlbnMtMCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBob3cgdG8gcmVjb2duaXplIGFuZCBoZWxwIHlvdXRocyBleHBlcmllbmNpbmcgc3ltcHRvbXMgb2YgZGVwcmVzc2lvbi4KCiMjICoqTGltaXRhdGlvbnMqKgoqKiogCgoKCmF2b2NhZG8gLU1pY2hhZWw6UGVyaGFwcyAidW5kZXJlc3RpbWF0ZXMgaW4gdGhlIHAtdmFsdWVzLi4uIiBpcyBub3QgdGhlIGNvcnJlY3Qgd2F5IHRvIHBocmFzZSB0aGlzLiBJIHdvdWxkIGxvb2sgZm9yIGEgYmV0dGVyIHdheSB0byB3b3JkIHRoaXMuLUNhcnJpZTpUaGlzIGlzIG15IGF0dGVtcHQgYWZ0ZXIgTWljaGFlbCdzLi4uIG9wZW4gdG8gY2hhbmdlcyEKCgpUaGVyZSBhcmUgc29tZSBpbXBvcnRhbnQgY29uc2lkZXJhdGlvbnMgcmVnYXJkaW5nIHRoaXMgZGF0YSBhbmFseXNpcyB0byBrZWVwIGluIG1pbmQ6IAoKMSkgVGhlIGRhdGEgdGhhdCB3ZSB3aWxsIHVzZSBjb21lIGZyb20gYSBzdXJ2ZXkgYW5kIGFyZSB0aGVyZWZvcmUgdmFsdWVzIGZyb20gYSBzYW1wbGUgdGhhdCBlc3RpbWF0ZSB0aGF0IG9mIHRoZSB0cnVlIHBvcHVsYXRpb24uIEluIG91ciBzdGF0aXN0aWNhbCBhbmFseXNpcyB3ZSB1c2UgdGhlc2Ugc2FtcGxlIHZhbHVlcyBhcyBpZiB0aGV5IGFyZSBwb3B1bGF0aW9uIGVzdGltYXRlcyAoYmVjYXVzZSB0aGlzIGlzIGFsbCB3ZSBoYXZlIGFjY2VzcyB0bykuIFRodXMgb3VyIHJlc3VsdHMgYXJlIG5vdCBuZWNlc3NhcmlseSBpbmRpY2F0aXZlIG9mIHRydWUgZGlmZmVyZW5jZXMuCgoyKSBGdXJ0aGVybW9yZSwgdGhlIHNhbXBsaW5nIG1lY2hhbmlzbSB1dGlsaXplZCBjYW4gaW50cm9kdWNlIFtzZWxlY3Rpb24gYmlhc10oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2VsZWN0aW9uX2JpYXM/b2xkZm9ybWF0PXRydWUpe3RhcmdldD0iX2JsYW5rIn0gaW4gY2FzZXMgd2hlcmUgdGhlIHRoZSBbc2FtcGxpbmcgbWV0aG9kcyBkbyBub3QgcHJvZHVjZSBhIHJlcHJlc2VudGF0aXZlIHNhbXBsZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvU2FtcGxpbmdfKHN0YXRpc3RpY3MpP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9LiAKCjMpIERhdGEgaXMgY29sbGVjdGVkIGZyb20gaHVtYW4gcGFydGljaXBhbnRzOyB0aGlzIHByZXNlbnRzIHRoZSAqcG90ZW50aWFsKiBmb3IgaW5mb3JtYXRpb24gYmlhcywgYXMgdGhlcmUgaXMgdGhlICpwb3RlbnRpYWwqIHRoYXQgcGFydGljaXBhbnRzIGluIHRoZSBbc2FtcGxpbmcgZnJhbWVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXBsaW5nX2ZyYW1lP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9IG1heSBmb3IgYSB2YXJpZXR5IG9mIHJlYXNvbnMgcmVwb3J0IGluYWNjdXJhdGUgaW5mb3JtYXRpb24uIAoKIyMgKipXaGF0IGFyZSB0aGUgZGF0YT8qKgoqKiogCgpXZSB3aWxsIGJlIHVzaW5nIGRhdGEgZnJvbSB0aGUgW05hdGlvbmFsIFN1cnZleSBvbiBEcnVnIFVzZSBhbmQgSGVhbHRoIChOU0RVSCldKGh0dHBzOi8vbnNkdWh3ZWIucnRpLm9yZy9yZXNwd2ViL2hvbWVwYWdlLmNmbSl7dGFyZ2V0PSJfYmxhbmsifSB3aGljaCBpcyBkaXJlY3RlZCBieSB0aGUgW1N1YnN0YW5jZSBBYnVzZSBhbmQgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBBZG1pbmlzdHJhdGlvbiAoU0FNSFNBKV0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0sIGFuIGFnZW5jeSBpbiB0aGUgW1UuUy4gRGVwYXJ0bWVudCBvZiBIZWFsdGggYW5kIEh1bWFuIFNlcnZpY2VzIChESEhTKV0oaHR0cHM6Ly93d3cuaGhzLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0uIAoKVGhpcyBzdXJ2ZXkgc3RhcnRlZCBpbiAxOTcxIGFuZCBpcyBjb25kdWN0ZWQgYW5udWFsbHkgaW4gYWxsIDUwIHN0YXRlcyBhbmQgdGhlIERpc3RyaWN0IG9mIENvbHVtYmlhLiBBcHByb3hpbWF0ZWx5IDcwLDAwMCBwZW9wbGUgKGFnZSAxMiBhbmQgdXApIGFyZSBpbnRlcnZpZXdlZCBlYWNoIHllYXIgYWJvdXQgaGVhbHRoIHJlbGF0ZWQgaXNzdWVzLiBPbmx5IGNpdmlsaWFuLCBub24taW5zdGl0dXRpb25hbGl6ZWQgaW5kaXZpZHVhbHMgYXJlIGluY2x1ZGVkLiBIb3VzZWhvbGRzIGFyZSByYW5kb21seSBzZWxlY3RlZCBhbmQgdGhhbiBhIHByb2Zlc3Npb25hbCBpbnRlcnZpZXdlciB2aXNpdHMgdGhlIGFkZHJlc3NlcyBhbmQgYXNrcyBvbmUgb3IgdHdvIG9mIHRoZSByZXNpZGVudHMgdG8gaW50ZXJ2aWV3LiBUaGUgaW50ZXJ2aWV3ZXIgYnJpbmdzIGEgbGFwdG9wIHdpdGggdGhlbSB0aGF0IHRoZSBwYXJ0aWNpcGFudHMgdXNlIHRvIGZpbGwgb3V0IHRoZSBzdXJ2ZXkgd2hpY2ggdHlwaWNhbGx5IHRha2VzIGFuIGhvdXIgdG8gY29tcGxldGUuIElmIGEgcGFydGljaXBhbnQgY2hvb3NlcyB0byBwYXJ0aWNpcGF0ZSB0aGV5IHJlY2VpdmUgJDMwIGluIGNhc2guIEFsbCBjb2xsZWN0ZWQgaW5mb3JtYXRpb24gaXMgY29uZmlkZW50aWFsIGFuZCBpcyB1c2VkIGZvciBkaXNlYXNlIHN1cnZlaWxsYW5jZSBhbmQgdG8gZ3VpZGUgcHVibGljIHBvbGljeSBwYXJ0aWN1bGFybHkgZm9jdXNlZCBvbiBkcnVnIGFuZCBhbGNvaG9sIHVzZSBhcyB3ZWxsIGFzIG1lbnRhbCBoZWFsdGguIFNlZSBbaGVyZV0oaHR0cHM6Ly9uc2R1aHdlYi5ydGkub3JnL3Jlc3B3ZWIvYWJvdXRfbnNkdWguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IHRoZSBzdXJ2ZXkuCgpUaGlzIGRhdGEgaXMgbWFkZSBhdmFpbGFibGUgcHVibGljbHkgb25saW5lIG9uIHRoZSBbU3Vic3RhbmNlIEFidXNlICYgTWVudGFsIEhlYWx0aCBEYXRhIEFyY2hpdmVdKGh0dHBzOi8vZGF0YWZpbGVzLnNhbWhzYS5nb3YvKXt0YXJnZXQ9Il9ibGFuayJ9LiAKCmBgYHtyLCBvdXQud2lkdGggPSAiMTAwJSIsIGVjaG8gPSBGQUxTRSwgZmlnLmFsaWduID0iY2VudGVyIn0KaW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAibnN1ZGhfc2NyZWVuc2hvdF93ZWJwYWdlLnBuZyIpKQpgYGAKCkF0IHRoZSBbd2Vic2l0ZV0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL3NpdGVzL2RlZmF1bHQvZmlsZXMvY2Joc3EtcmVwb3J0cy9OU0RVSERldGFpbGVkVGFiczIwMThSMi9OU0RVSERldFRhYnNTZWN0MTFwZTIwMTguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciB0aGUgc3VydmV5IGRhdGEsIHlvdSBjYW4gc2VlIHRoYXQgdGhlIHJlc3VsdHMgYXJlIGRpc3BsYXllZCBpbiBtYW55IHRhYmxlcy4gSW1wb3J0YW50bHksIHRoZXJlIGlzIG5vIG9idmlvdXMgd2F5IHRvIGRvd25sb2FkIHRoZSBkYXRhIGRpcmVjdGx5IGZyb20gdGhpcyBwYXJ0aWN1bGFyIHdlYnNpdGUuCgpgYGB7ciwgb3V0LndpZHRoID0gIjEwMCUiLCBlY2hvID0gRkFMU0UsIGZpZy5hbGlnbiA9ImNlbnRlciJ9CmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIndlYnNpdGVfb3ZlcnZpZXcucG5nIikpCmBgYAoKSWYgb25lIGNsaWNrcyBvbiB0aGUgVE9DIGJ1dHRvbiBvbiB0aGUgZmFyIHJpZ2h0IHVwcGVyIGNvcm5lciB0aGV5IHdpbGwgYmUgZGlyZWN0ZWQgdG8gYW5vdGhlciBbd2Vic2l0ZV0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL3NpdGVzL2RlZmF1bHQvZmlsZXMvY2Joc3EtcmVwb3J0cy9OU0RVSERldGFpbGVkVGFiczIwMThSMi9OU0RVSERldGFpbGVkVGFic1RPQzIwMTguaHRtI3RvYyl7dGFyZ2V0PSJfYmxhbmsifSwgd2hlcmUgYSBsYXJnZSBbcGRmIGRvY3VtZW50XShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0YWlsZWRUYWJzMjAxOC5wZGYpe3RhcmdldD0iX2JsYW5rIn0gY29udGFpbmluZyBvZiBhbGwgb2YgdGhlIHJlc3VsdHMgY2FuIGJlIGRvd25sb2FkZWQuCgpXZSBhcmUgaW50ZXJlc3RlZCBpbiBpbnZlc3RpZ2F0aW5nIGhvdyBkZXByZXNzaW9uIHJhdGVzIGhhdmUgY2hhbmdlZCBhbmQgaG93IHlvdXRocyBhcmUgaW50ZXJhY3Rpbmcgd2l0aCBtZW50YWwgaGVhbHRoIHNlcnZpY2VzLiBUaHVzIHRoZSBmb2xsb3dpbmcgdGFibGVzIGFyZSBvZiBpbnRlcmVzdCB0byB1cyBhcmU6CgpUYWJsZSAgIHwgRGV0YWlscyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tfC0tLS0tLS0tLS0tLS0KVGFibGUgMTEuMUEgICAgICAgfCBTZXR0aW5ncyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VzIFdlcmUgUmVjZWl2ZWQgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNzogTnVtYmVycyBpbiBUaG91c2FuZHMsIDIwMDItMjAxOCAgIApUYWJsZSAxMS4xQiAgICAgICB8IFNldHRpbmdzIFdoZXJlIE1lbnRhbCBIZWFsdGggU2VydmljZXMgV2VyZSBSZWNlaXZlZCBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3OiBQZXJjZW50YWdlcywgMjAwMi0yMDE4ICAKVGFibGUgMTEuMkEgICAgICAgfCAgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogTnVtYmVycyBpbiBUaG91c2FuZHMsIDIwMDQtMjAxOApUYWJsZSAxMS4yQiAgICAgICB8IE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3LCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgKVGFibGUgMTEuM0EgICAgICAgfCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgd2l0aCBTZXZlcmUgSW1wYWlybWVudCBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3LCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IE51bWJlcnMgaW4gVGhvdXNhbmRzLCAyMDA2LTIwMTgKVGFibGUgMTEuM0IgICAgICAgfCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgd2l0aCBTZXZlcmUgSW1wYWlybWVudCBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3LCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IFBlcmNlbnRhZ2VzLCAyMDA2LTIwMTgKVGFibGUgMTEuNEEgICAgICAgfCBSZWNlaXB0IG9mIFRyZWF0bWVudCBmb3IgRGVwcmVzc2lvbiBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IHdpdGggTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhciwgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBOdW1iZXJzIGluIFRob3VzYW5kcywgMjAwNC0yMDE4ClRhYmxlIDExLjRCICAgICAgIHwgUmVjZWlwdCBvZiBUcmVhdG1lbnQgZm9yIERlcHJlc3Npb24gaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyB3aXRoIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDQtMjAxOAoKCkFjY29yZGluZyB0byB0aGUgW05TRFVIIDIwMTggcmVwb3J0XShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVITmF0aW9uYWxGaW5kaW5nc1JlcG9ydDIwMTgvTlNEVUhOYXRpb25hbEZpbmRpbmdzUmVwb3J0MjAxOC5wZGYpe3RhcmdldD0iX2JsYW5rIn0KCgo+IFJlc3BvbmRlbnRzIHdlcmUgZGVmaW5lZCBhcyBoYXZpbmcgaGFkIGFuIE1ERSBpbgp0aGUgcGFzdCAxMiBtb250aHMgaWYgdGhleSBoYWQgYXQgbGVhc3Qgb25lIHBlcmlvZCBvZiAyIHdlZWtzCm9yIGxvbmdlciBpbiB0aGUgcGFzdCB5ZWFyIHdoZW4gdGhleSBleHBlcmllbmNlZCBhIGRlcHJlc3NlZAptb29kIG9yIGxvc3Mgb2YgaW50ZXJlc3Qgb3IgcGxlYXN1cmUgaW4gZGFpbHkgYWN0aXZpdGllcywKYWNjb21wYW5pZWQgYnkgcHJvYmxlbXMgd2l0aCBzbGVlcGluZywgZWF0aW5nLCBlbmVyZ3ksCmNvbmNlbnRyYXRpb24sIG9yIHNlbGYtd29ydGguIFRoZSBNREUgcXVlc3Rpb25zIGFyZSBiYXNlZApvbiBkaWFnbm9zdGljIGNyaXRlcmlhIGZyb20gRFNNLTUuIFNvbWUgb2YgdGhlIHdvcmRpbmdzCm9mIHRoZSBkZXByZXNzaW9uIHF1ZXN0aW9ucyBmb3IgYWRvbGVzY2VudHMgYWdlZCAxMiB0byAxNwphbmQgYWR1bHRzIGFnZWQgMTggb3Igb2xkZXIgZGlmZmVyZWQgc2xpZ2h0bHkgdG8gbWFrZSB0aGUKcXVlc3Rpb25zIG1vcmUgZGV2ZWxvcG1lbnRhbGx5IGFwcHJvcHJpYXRlIGZvciBhZG9sZXNjZW50cy4KCj4gQWRvbGVzY2VudHMgd2VyZSBkZWZpbmVkIGFzIGhhdmluZyBhbiBNREUgd2l0aApzZXZlcmUgaW1wYWlybWVudCBpZiB0aGVpciBkZXByZXNzaW9uIGNhdXNlZCBzZXZlcmUgcHJvYmxlbXMKd2l0aCB0aGVpciBhYmlsaXR5IHRvIGRvIGNob3JlcyBhdCBob21lLCBkbyB3ZWxsIGF0IHdvcmsgb3IKc2Nob29sLCBnZXQgYWxvbmcgd2l0aCB0aGVpciBmYW1pbHksIG9yIGhhdmUgYSBzb2NpYWwgbGlmZS4KCgoKCiMjICoqRGF0YSBJbXBvcnQqKgoqKiogCgpEYXRhIGlzIG9mdGVuIG1hZGUgYXZhaWxhYmxlIG9ubGluZS4gVXN1YWxseSwgdGhlIGRhdGEgd2UgYXJlIGludGVyZXN0ZWQgaW4gaXMgbWFkZSBhdmFpbGFibGUgZm9yIGRvd25sb2FkIG9uIHRoZSBwYWdlIGFzIGEgZGVsaW1pdGVkIHRleHQgZmlsZSBvciBhbiBleGNlbCBmaWxlLiBIb3dldmVyLCBzb21ldGltZXMgZGF0YSBpcyBub3QgbWFkZSBhdmFpbGFibGUgaW4gdGhpcyBtYW5uZXIsIHN1Y2ggYXMgdGhlIFtOU0RVSCBzdXJ2ZXkgZGF0YV0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL3NpdGVzL2RlZmF1bHQvZmlsZXMvY2Joc3EtcmVwb3J0cy9OU0RVSERldGFpbGVkVGFiczIwMThSMi9OU0RVSERldFRhYnNTZWN0MTFwZTIwMTguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9LgoKSG93IGRvIHdlIHByb2NlZWQgaW4gdGhpcyBzY2VuYXJpbz8KCldlIGNhbiBtYW51YWxseSBjb3B5IGVhY2ggY2VsbCBvZiBkYXRhLCBob3dldmVyLCB0aGlzIHByb2Nlc3MgaXMgb2Z0ZW4gaW5lZmZpY2llbnQsIHN1YmplY3QgdG8gZXJyb3IsIGFuZCBub3QgcmVwcm9kdWNpYmxlLiBTYXkgd2Ugd2FudGVkIHRvIHJ1biBhbiBhbmFseXNpcyBuZXh0IHllYXIgb24gdGhlIG5leHQgeWVhcnMgZGF0YSBhbmQgaXQgaGFwcGVucyB0byBiZSBmb3JtYXR0ZWQgaW4gdGhlIHNhbWUgd2F5LiAKCldlIGNhbiBhbHNvIHVzZSBgUmAgZm9yIHdlYiBzY3JhcGluZy4gCgpbV2ViIHNjcmFwaW5nXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XZWJfc2NyYXBpbmc/b2xkZm9ybWF0PXRydWUpe3RhcmdldD0iX2JsYW5rIn0gaXMgdGhlIHByb2Nlc3Mgb2YgZXh0cmFjdGluZyBkYXRhIGZyb20gYSB3ZWJzaXRlLgoKCiMjIyBCYXNpYyBzdGVwcyBvZiB3ZWIgc2NyYXBpbmcKClRoZXJlIGFyZSB0d28gbWFpbiBzdGVwcyB0byB3ZWIgc2NyYXBpbmc6ICAKCjEuIElkZW50aWZ5IGxvY2F0aW9uIG9mIGRhdGEgb24gdGhlIHdlYnBhZ2UgdGhhdCB3aWxsIGJlIHNjcmFwZWQgIAoKMi4gU2F2ZSB0aGUgd2VicGFnZSBlbGVtZW50IHRvIGFuIG9iamVjdCAgCgpXZSBhY2NvbXBsaXNoIFNURVAgMSB3aXRoIG91ciB3ZWIgYnJvd3Nlci4KCldlIGFjY29tcGxpc2ggU1RFUCAyIGluIHRoZSBgUmAgcHJvZ3JhbW1pbmcgZW52aXJvbm1lbnQuIAoKIyMjIyB7LnJlc291cmNlX2Jsb2NrfSAKCjx1PkFkZGl0aW9uYWwgcmVzb3VyY2VzIGZvciB3ZWIgc2NyYXBpbmc8L3U+OgoKLSBbVmlnbmV0dGVdKGh0dHBzOi8vcnN0dWRpby1wdWJzLXN0YXRpYy5zMy5hbWF6b25hd3MuY29tLzI2NjQzMF9mM2ZkNDY2MGIyNzQ0NzUxYWIxNDRhYTEzMDc2OGEwNi5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9Ci0gW0Jsb2ddKGh0dHA6Ly9ibG9nLmNvcnluaXNzZW4uY29tLzIwMTUvMDEvdXNpbmctcnZlc3QtdG8tc2NyYXBlLWh0bWwtdGFibGUuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifQotIFtCbG9nXShodHRwOi8vcmVzZWFyY2gubGliZC5vcmcvcnN0YXRzY2x1Yi9wb3N0L2ludHJvZHVjdGlvbi10by1zY3JhcGluZy1hbmQtd3JhbmdpbmctdGFibGVzLWZyb20tcmVzZWFyY2gtYXJ0aWNsZXMvIy5Ydzg3OFpOS2hRSil7dGFyZ2V0PSJfYmxhbmsifQotIFtTZWxlY3RvcmdhZGdldCBUb29sXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcnZlc3QvdmlnbmV0dGVzL3NlbGVjdG9yZ2FkZ2V0Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0KCiMjIyMKCkluIHRoaXMgY2FzZSBzdHVkeSB3ZSB3aWxsIHNjcmFwZSBkYXRhIGZyb20gdGhlIHRhYmxlcyBvbiB0aGUgW05TRFVIIHN1cnZleV0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL3NpdGVzL2RlZmF1bHQvZmlsZXMvY2Joc3EtcmVwb3J0cy9OU0RVSERldGFpbGVkVGFiczIwMThSMi9OU0RVSERldFRhYnNTZWN0MTFwZTIwMTguaHRtKXt0YXJnZXQ9Il9ibGFuayJ9IHdlYnNpdGUuIFRoaXMgZGF0YSBpcyBhdmFpbGFibGUgaW4gYSBsYXJnZSBQREYgd2l0aCBhbGwgdGhlIHJlc3VsdHMgZm9ybSB0aGUgeWVhci4gSG93ZXZlciBpdCBpcyBub3QgZWFzeSB0byBmaW5kIHRoaXMgUERGIGFuZCBpdCB3b3VsZCBiZSBkaWZmaWN1bHQgYW5kIHRpbWUgY29uc3VtaW5nIHRvIGZpbmQgb3VyIHRhYmxlcyBvZiBpbnRlcmVzdCBhbmQgdG8gZXh0cmFjdCB0aGUgZGF0YSBmcm9tIHRoZSBwZGYgd2l0aCBgcGRmdG9vbHNgLiBBZ2FpbiwgaWYgd2UgaW5zdGVhZCBkZWNpZGVkIHRvIGNvcHkgcGFzdGUgdGhlIGRhdGEgZnJvbSB0aGUgd2Vic2l0ZSB0byBhbm90aGVyIGZpbGUgdGhhdCB3ZSB3b3VsZCBhbHNvIG5lZWQgdG8gaW1wb3J0LCB0aGlzIHdvdWxkIG5vdCBiZSBhcyBlZmZpY2llbnQgb3IgcmVwcm9kdWNpYmxlIGFuZCBtaWdodCByZXN1bHQgaW4gZXJyb3JzLiAKCgpBbHRlcm5hdGl2ZWx5LCB3ZSB3aWxsIHVzZSB0aGUgYHJ2ZXN0YCBwYWNrYWdlIHRvIFtzY3JhcGVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9zY3JhcGluZz9vbGRmb3JtYXQ9dHJ1ZSl7dGFyZ2V0PSJfYmxhbmsifSB0aGUgZGF0YSBkaXJlY3RseSBmcm9tIHRoZSB0YWJsZXMgb24gdGhlIHdlYnNpdGUuIEFzc3VtaW5nIHRoZSBkYXRhIG5leHQgeWVhciB3b3VsZCBiZSBkaXNwbGF5ZWQgaW4gYSBzaW1pbGFyIG1hbm5lciwgdGhpcyBjb3VsZCBhbGxvdyB1cyBzaW1wbHkgbW9kaWZ5IG91ciBjb2RlIGJhc2VkIG9uIHRoZSB1cmwgZm9yIHRoZSBkYXRhIG5leHQgeWVhciB0byBydW4gdGhlIHNhbWUgYW5hbHlzaXMgb24gdGhlIGRhdGEgZWFzaWx5LiAKClRoZSBgcnZlc3RgICBwYWNrYWdlIGNhbiBiZSB0aG91Z2h0IG9mIGFzIHRoZSBgcGRmdG9vbHNgIHBhY2thZ2UgZm9yIHdlYiBzY3JhcGluZy4gVXBvbiBwdWxsaW5nIHRoZSBkYXRhLCBhZGRpdGlvbmFsIHdyYW5nbGluZyB3aWxsIGxpa2VseSBiZSByZXF1aXJlZDsgYnV0IGxpa2UgdGhlIGBwZGZ0b29sc2AgcGFja2FnZSwgYHJ2ZXN0YCBzdHJlYW1saW5lcyB0aGUgZXh0cmFjdGlvbiBwcm9jZXNzLiAgCgojIyMgU3RlcHMgZm9yIHNjcmFwaW5nIHRhYmxlcwoKVGhlIHR3byB3ZWIgc2NyYXBpbmcgc3RlcHMgZm9yIHRoZXNlIHRhYmxlcyBjYW4gYmUgYnJva2VuIGRvd24gZXZlbiBmdXJ0aGVyOiAKCjEpIElkZW50aWZ5IGxvY2F0aW9uIG9mIGRhdGEgdGhhdCB3aWxsIGJlIHNjcmFwZWQKCisgcmlnaHQtY2xpY2sgdG8gaW5zcGVjdCBlbGVtZW50ICh3ZWJwYWdlKQorIGhvdmVyIHBvaW50ZXIgb3ZlciBjb21wb25lbnRzIG9mIGVsZW1lbnQgKHdlYnBhZ2UpIHVudGlsIHRoZSBkYXRhIGhhcyBiZWVuIGZvdW5kCisgY29weSBYUGF0aCBvZiBkYXRhIHNvdWdodAoKMikgU2F2ZSB3ZWJwYWdlIGVsZW1lbnQgdG8gYW4gb2JqZWN0IGluIFIKCisgaW1wb3J0IGh0bWwgY29kZSBmb3IgdGhlIHdlYnBhZ2UKKyBleHRyYWN0IHBpZWNlcyBvZiBIVE1MIGRvY3VtZW50cyAod2VicGFnZSkgdXNpbmcgWFBhdGgKKyBwYXJzZSB0aGUgZXh0cmFjdGVkIGRhdGEgaW50byBhIGRhdGEgZnJhbWUKCkJlbG93IGlzIGEgYW5pbWF0ZWQgb3ZlcnZpZXcgb2YgdGhlIHByb2Nlc3MuCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpzdGVwMSA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsIAoid2VicGFnZV9zY3JlZW5zaG90LnBuZyIpKQpzdGVwMiA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X2luc3BlY3QucG5nIikpCnN0ZXAzIDwtIGltYWdlX3JlYWQoaGVyZTo6aGVyZSgiaW1nIiwgInRhYmxlX3NjcmVlbnNob3RfaW5zcGVjdF90YWJsZS5wbmciKSkKc3RlcDQgPC0gaW1hZ2VfcmVhZChoZXJlOjpoZXJlKCJpbWciLCAidGFibGVfc2NyZWVuc2hvdF9pbnNwZWN0X3RhYmxlX3hwYXRoLnBuZyIpKQpzdGVwNSA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X3hwYXRoX2NvcHlfci5wbmciKSkKc3RlcDVfem9vbSA8LSBpbWFnZV9yZWFkKGhlcmU6OmhlcmUoImltZyIsICJ0YWJsZV9zY3JlZW5zaG90X3hwYXRoX2NvcHlfcl96b29tLnBuZyIpKQpgYGAKCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvPUZBTFNFfQppbWFnZV9pbmZvKHN0ZXA1X3pvb20pCgpzdGVwNV96b29tIDwtIGltYWdlX2JvcmRlcihzdGVwNV96b29tLCAid2hpdGUiLCAiMjg0eDMzNCIpCgppbWcgPC0gYyhzdGVwMSwKICAgICAgICAgc3RlcDIsCiAgICAgICAgIHN0ZXAyLAogICAgICAgICBzdGVwMywKICAgICAgICAgc3RlcDMsCiAgICAgICAgIHN0ZXA0LAogICAgICAgICBzdGVwNCwKICAgICAgICAgc3RlcDUsCiAgICAgICAgIHN0ZXA1LAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwNV96b29tLAogICAgICAgICBzdGVwMSkKCmVkdWNhdGlvbmFsX2dpZiA8LSBpbWFnZV9yZXNpemUoaW1nLCAnMTQ0MHg5MDAhJykgJT4lCiAgaW1hZ2VfYmFja2dyb3VuZCgnd2hpdGUnKSAlPiUKICBpbWFnZV9tb3JwaChmcmFtZXMgPSAxMCkgJT4lCiAgaW1hZ2VfYW5pbWF0ZShkZWxheSA9IDIwLAogICAgICAgICAgICAgICAgb3B0aW1pemUgPSBUUlVFKQoKaW1hZ2Vfd3JpdGUoZWR1Y2F0aW9uYWxfZ2lmLAogICAgICBoZXJlOjpoZXJlKCJpbWciLCAiZWR1Y2F0aW9uYWwuZ2lmIikpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsImVkdWNhdGlvbmFsLmdpZiIpKQpgYGAKCioqKgoKTm93IGxldCdzIGdvIHRocm91Z2ggZWFjaCBzdGVwIHRvZ2V0aGVyOgoKIyMjIDEpIElkZW50aWZ5IGxvY2F0aW9uIG9mIGRhdGEgdGhhdCB3aWxsIGJlIHNjcmFwZWQKCkZpcnN0LCBsZXQncyBnbyB0byB0aGUgW3dlYiBwYWdlXShodHRwczovL3d3dy5zYW1oc2EuZ292L2RhdGEvc2l0ZXMvZGVmYXVsdC9maWxlcy9jYmhzcS1yZXBvcnRzL05TRFVIRGV0YWlsZWRUYWJzMjAxOFIyL05TRFVIRGV0VGFic1NlY3QxMXBlMjAxOC5odG0pe3RhcmdldD0iX2JsYW5rIn0gd2l0aCBhbGwgdGhlIHRhYmxlcyB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBzY3JhcGluZwoKYGBge3IsIHN0ZXAxLCBlY2hvPUZBTFNFfQpzdGVwMQpgYGAKCk9uY2Ugb24gdGhlIHdlYnBhZ2UsIHRoZXJlIGFyZW4ndCBhbnkgdmlzaWJsZSBvcHRpb25zIHRvIGRvd25sb2FkIHRoZSBkYXRhLiAKClJpZ2h0LWNsaWNrIGFuZCBzZWxlY3QgIkluc3BlY3QiIAoKYGBge3IsIHN0ZXAyLCBlY2hvPUZBTFNFfQpzdGVwMgpgYGAKCkEgd2luZG93IG9wZW5zLiAKClRoaXMgd2luZG93IGFsbG93cyB1cyB0byBnbGFuY2UgYXQgdGhlIGludGVybmFsIG1lY2hhbmljcyBvZiB0aGUgd2VicGFnZS4gVG8gc2NyYXBlIHRoZSBkYXRhIGZyb20gdGhlIHdlYnBhZ2UsIHdlIG5lZWQgdG8gZmlyc3QgbGVhcm4gYSBsaXR0bGUgYml0IGFib3V0IHRoZSBjb21wb25lbnRzIHRoYXQgbWFrZSBpdCB0aGUgd2ViIHBhZ2UgaXQgaXMuIAoKSG92ZXJpbmcgb3VyIG1vdXNlIG92ZXIgdGhlIGVsZW1lbnRzIG9mIHRoZSB3ZWJwYWdlIGhpZ2hsaWdodHMgdGhlIHJlc3BlY3RpdmUgc2VjdGlvbiBvZiB0aGUgd2VicGFnZSBpdCByZXByZXNlbnRzLiBCeSBob3ZlcmluZyBvdmVyIHNldmVyYWwgZWxlbWVudHPigJRhbmQgY2xpY2tpbmcgb24gdGhlIGVsZW1lbnRzIG9uIHRoZSByaWdodCBzaWRlIG9mIHRoZSBzY3JlZW7igJR3ZSBjYW4gaWRlbnRpZnkgdGhlIGVsZW1lbnQgdGhhdCBjb250YWlucyB0aGUgZGF0YSB3ZSBhcmUgbG9va2luZyBmb3IuIEFub3RoZXIgb3B0aW9uIGZvciBpZGVudGlmeWluZyBYUGF0aHMgaXMgdG8gdXNlIHRoZSBbc2VsZWN0b3JnYWRnZXQgdG9vbF0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL3J2ZXN0L3ZpZ25ldHRlcy9zZWxlY3RvcmdhZGdldC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9LiAgCgpgYGB7cixzdGVwMywgZWNobz1GQUxTRX0Kc3RlcDMgCmBgYAoKUmlnaHQgY2xpY2sgb24gdGhlIGVsZW1lbnQgYW5kIGNvcHkgdGhlIFhQYXRoLiBXZSB3aWxsIG5lZWQgdGhpcyBYUGF0aCBmb3IgdGhlIG5leHQgc3RlcC4KCmBgYHtyLCBzdGVwNCwgZWNobz1GQUxTRX0Kc3RlcDQKYGBgCgpOb3cgd2UgY2FuIHJldHVybiB0byB0aGUgYFJgIHByb2dyYW1taW5nIGVudmlyb25tZW50LgoKYGBge3IsIHN0ZXA1LCBlY2hvPUZBTFNFfQpzdGVwNQpgYGAKCioqKgoKIyMjIDIpIFNhdmUgd2VicGFnZSBlbGVtZW50IHRvIGFuIG9iamVjdCBpbiBSIAoKRm9yIHRoZSBmaXJzdCB0YWJsZSB3ZSB3YW50IHRvIHNjcmFwZSwgdGhlIFhQYXRoIGlzIGAvaHRtbC9ib2R5L2Rpdls0XS9kaXZbMV0vdGFibGVgLiBXZSB1c2UgdGhpcyBYUGF0aCB3aXRoIGZ1bmN0aW9ucyBmcm9tIHRoZSBgcnZlc3RgIHBhY2thZ2UgdG8gc2NyYXBlIHRoZSBkYXRhIGZyb20gdGhpcyB0YWJsZS4KCgpgYGB7cixzdGVwNV96b29tLCBlY2hvPUZBTFNFfQpzdGVwNV96b29tCmBgYAoKCkxldCdzIGV4cGxvcmUgdGhpcyBzdGVwIGluIGdyZWF0ZXIgZGV0YWlsOgoKV2UgbmVlZCB0bzoKCisgaW1wb3J0IGh0bWwgY29kZSBmb3IgdGhlIHdlYnBhZ2UKKyBleHRyYWN0IHBpZWNlcyAodGFibGUpIG91dCBvZiBIVE1MIGRvY3VtZW50cyAod2VicGFnZSkgdXNpbmcgWFBhdGgKKyBwYXJzZSB0aGUgaHRtbCB0YWJsZSBpbnRvIGEgZGF0YSBmcmFtZQoKVG8gZG8gdGhpczoKCisgV2UgaW1wb3J0IHRoZSBodG1sIGNvZGUgdXNpbmcgdGhlIGByZWFkX2h0bWwoKWAgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZQorIFdlIGV4dHJhY3Qgc3BlY2lmaWMgY29tcG9uZW50cyBvZiB0aGUgd2VicGFnZSB1c2luZyB0aGUgYGh0bWxfbm9kZXMoKWAgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZQorIFdlIGNvbnZlcnQgdGhpcyBodG1sIHRhYmxlIGludG8gYSBkYXRhZnJhbWUgdXNpbmcgdGhlIGBodG1sX3RhYmxlKClgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZQoKKipUaGUgYHJ2ZXN0YCBwYWNrYWdlIHByb3ZpZGVzIHdyYXBwZXJzIGZvciB0aGUgYHhtbDJgIGFuZCBgaHR0cmAgcGFja2FnZXMsIHRodXMgd2UgY2FuIGp1c3QgaW5zdGFsbCBhbmQgbG9hZCB0aGUgYHJ2ZXN0YCBwYWNrYWdlIGFuZCBpdCB3aWxsIGluc3RhbGwgYW5kIGxvYWQgZGVwZW5kZW5jeSBwYWNrYWdlcyBsaWtlIGB4bWwyYCBhbmQgYGh0dHJgIGFuZCBhbGxvdyB1cyB0byB1c2UgZnVuY3Rpb25zIGZyb20gIGJvdGggb2YgdGhlc2UgcGFja2FnZXMuKioKCkluIGZhY3QsIHdoZW4gd2UgbG9hZCBgcnZlc3RgIHRoZSBmaXJzdCB0aW1lIHdlIHNlZToKCmBgYHtyLCBvdXQud2lkdGg9ICI2MCUifQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAicnZlc3QucG5nIikpCmBgYAoKSW4gdGhpcyBjYXNlLCB3ZSBhcmUgc2NyYXBpbmcgdGFibGUgMTEuMWEgZnJvbSB0aGUgd2Vic2l0ZS4gRmlyc3Qgd2UgYXNzaWduIHRoZSB1cmwgdG8gYSBjaGFyYWN0ZXIgc3RyaW5nIHRvIHVzZSB3aXRoaW4gdGhlIGByZWFkX2h0bWwoKWAgZnVuY3Rpb24gb2YgdGhlIGB4bWwyYCBwYWNrYWdlLiAKCmBgYHtyfQpOU0RVSF91cmwgPC0gImh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRUYWJzU2VjdDExcGUyMDE4Lmh0bSIKYGBgCgpPbmUgY291bGQgYWxzbyBkaXJlY3RseSB1c2UgdGhlIHVybCBidXQgdGhpcyBpcyBsZXNzIGNvbnZlbmllbnQgZm9yIHBpcGluZy4gIAoKPGRldGFpbHM+IDxzdW1tYXJ5PkNsaWNrIGhlcmUgaWYgeW91IGFyZSB1bmZhbWlsaWFyIHdpdGggcGlwaW5nIGluIFIsIHdoaWNoIHVzZXMgdGhpcyBgJT4lYCBvcGVyYXRvcjwvc3VtbWFyeT4gIAoKQnkgW3BpcGluZ10oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ3JpdHRyL3ZpZ25ldHRlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IHdlIG1lYW4gdXNpbmcgdGhlIGAlPiVgIHBpcGUgb3BlcmF0b3Igd2hpY2ggYXJlIHVzYWJsZSB3aGVuIGxvYWRpbmcgdGhlIHRpZHl2ZXJzZSBvciBzZXZlcmFsIG9mIHRoZSBwYWNrYWdlcyB3aXRoaW4gdGhlIHRpZHl2ZXJzZSBsaWtlIGBkcGx5cmAgYmVjYXVzZSB0aGV5IGxvYWQgdGhlIFtgbWFncml0dHJgIHBhY2thZ2VdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9tYWdyaXR0ci92aWduZXR0ZXMvbWFncml0dHIuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifS4gVGhpcyBhbGxvd3MgdXMgdG8gcGVyZm9ybSBtdWx0aXBsZSBzZXF1ZW50aWFsIHN0ZXBzIG9uIG9uZSBkYXRhIGlucHV0LiAgIAoKPC9kZXRhaWxzPiAgCgogIApUaGUgYHJlYWRfaHRtbCgpYCBmdW5jdGlvbiB0aGVuIGFsbG93cyB1cyB0byBzYXZlIHRoZSBodG1sIGRvY3VtZW50IGZvciB0aGUgd2VicGFnZSBpbnNpZGUgUi4gCgpgYGB7cn0Kd2VicGFnZSA8LSBOU0RVSF91cmwgJT4lCiAgeG1sMjo6cmVhZF9odG1sKCkgCndlYnBhZ2UKYGBgCgpUaGVuIHdlIHVzZSB0aGUgYGh0bWxfbm9kZXMoKWAgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZSB0byBzZWxlY3QganVzdCB0aGUgdGFibGUxMS4xYSBlbGVtZW50IG9mIHRoZSB3ZWJwYWdlLgoKU2VlIHRoaXMgW3R1dG9yaWFsXShodHRwOi8vZmx1a2VvdXQuZ2l0aHViLmlvLyMpe3RhcmdldD0iX2JsYW5rIn0gKGFuZCB0aGUgW2Fuc3dlcnNdKGh0dHBzOi8vZ2lzdC5naXRodWIuY29tL2NocmlzbWFuL2ZjYjBhODg0NTljZDk4MjM5ZGJlNmQyZDIwMGIwMmQxKXt0YXJnZXQ9Il9ibGFuayJ9IGluIGNhc2UgeW91IGdldCBzdHVjaykgb24gQ1NTIHNlbGVjdG9ycyB0byB1bmRlcnN0YW5kIG1vcmUgYWJvdXQgaG93IHRoaXMgZnVuY3Rpb24gd29ya3MgdG8gdXNlIHRoZSBgeHBhdGhgIHRvIHNlbGVjdCB0aGUgZWxlbWVudHMgb2YgaW50ZXJlc3QgZnJvbSB0aGUgd2VicGFnZS4KCgpgYGB7cn0Kd2VicGFnZV9lbGVtZW50IDwtd2VicGFnZSAlPiUKICBydmVzdDo6aHRtbF9ub2Rlcyh4cGF0aD0nL2h0bWwvYm9keS9kaXZbNF0vZGl2WzFdL3RhYmxlJykKd2VicGFnZV9lbGVtZW50IAoKYGBgCgpGaW5hbGx5LCB0aGUgYGh0bWxfdGFibGUoKWAgZnVuY3Rpb24gb2YgdGhlIGBydmVzdGAgcGFja2FnZSBwYXJzZXMgdGhlIGh0bWwgb2JqZWN0IGludG8gYSBkYXRhIGZyYW1lLgoKYGBge3J9Cgp0YWJsZTExLjFhPC13ZWJwYWdlX2VsZW1lbnQlPiUKICBydmVzdDo6aHRtbF90YWJsZSgpCnByaW50KHRhYmxlMTEuMWEsIG1heCA9IDIpCmdsaW1wc2UodGFibGUxMS4xYSkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgdGhlIG91dHB1dCBpcyBhIGxpc3Qgd2l0aCBvbmUgZWxlbWVudCwgdG8gZXh0cmFjdCB0aGUgZGF0YSBmcm9tIHRoZSBsaXN0IHdlIHdpbGwgdXNlIGJyYWNrZXRzIGBbW11dYCB0byBzZWxlY3QgdGhlIGZpcnN0IGVsZW1lbnQgb2YgdGhlIGxpc3QuCmBgYHtyfQp0YWJsZTExLjFhIDwtIHRhYmxlMTEuMWFbWzFdXQpgYGAKCgpQdXR0aW5nIHRoaXMgYWxsIG9mIHRoaXMgdG9nZXRoZXIgd2UgY2FuIGRvIHRoZSBlbnRpcmUgcHJvY2VzcyBsaWtlIHRoaXMgd2l0aCBvdXIgcGlwZSBvcGVyYXRvciBgJT4lYC4KCmBgYHtyfQp0YWJsZTExLjFhIDwtIE5TRFVIX3VybCAlPiUKICB4bWwyOjpyZWFkX2h0bWwoKSAlPiUKICBydmVzdDo6aHRtbF9ub2Rlcyh4cGF0aD0nL2h0bWwvYm9keS9kaXZbNF0vZGl2WzFdL3RhYmxlJykgJT4lCiAgcnZlc3Q6Omh0bWxfdGFibGUoKQp0YWJsZTExLjFhIDwtIHRhYmxlMTEuMWFbWzFdXQpgYGAKCgpOb3cgbmVlZCB0byByZXBlYXQgdGhlIGFib3ZlIHByb2Nlc3MgZm9yIHRoZSBvdGhlciB0YWJsZXMgd2UgYXJlIGludGVyZXN0ZWQgaW4uIAoKIyMjIFdyaXRpbmcgYSBmdW5jdGlvbiB0byBzY3JhcGUgbXVsdGlwbGUgdGFibGVzCgpXZSBjYW4gY3JlYXRlIGEgZnVuY3Rpb24gdG8gYWNjb21wbGlzaCB0aGlzIHN1Y2NpbmN0bHkuIApGdW5jdGlvbnMgYWxsb3cgdXMgdG8gcGVyZm9ybSB0aGUgc2FtZSBwcm9jZXNzIG9uIG11bHRpcGxlIGRhdGEgaW5wdXRzLiBTZWUgW3RoaXMgb3RoZXIgY2FzZSBzdHVkeV0oaHR0cHM6Ly9vcGVuY2FzZXN0dWRpZXMuZ2l0aHViLmlvL29jcy1ibG9vbWJlcmctdmFwaW5nLWNhc2Utc3R1ZHkvKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGRldGFpbHMgYWJvdXQgaG93IHRvIHdyaXRlIGEgZnVuY3Rpb24uCgpJbiBnZW5lcmFsLCB0aGUgcHJvY2VzcyBwZiB3cml0aW5nIGZ1bmN0aW9ucyBpbnZvbHZlcyBmaXJzdCBzcGVjaWZ5aW5nIGFuIGlucHV0IHRoYXQgaXMgdXNlZCB3aXRoaW4gdGhlIGZ1bmN0aW9uIHRvIGNyZWF0ZSBhbiBvdXRwdXQuIEluIHRoaXMgY2FzZSB0aGUgZGF0YSBpbnB1dCBpcyBgWFBBVEhgIHdoaWNoIHdpbGwgYmUgcmVwbGFjZWQgYnkgYW4gYWN0dWFsIFhQYXRoIGFuZCB0aGVuIHVzZWQgaW4gdGhlIHN1YnNlcXVlbnQgc3RlcHMgdG8gc2NyYXBlIHRoZSBkYXRhIGZyb20gZWFjaCB0YWJsZSB0aGF0IGFuIFhQYXRoIGlzIHN1cHBsaWVkIGZvci4KCldlIHdpbGwgYWxsIHRoaXMgZnVuY3Rpb24gYHNjcmFwZXJgLgoKYGBge3J9CnNjcmFwZXIgPC0gZnVuY3Rpb24oWFBBVEgpewogIE5TRFVIX3VybCA8LSAiaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi9kYXRhL3NpdGVzL2RlZmF1bHQvZmlsZXMvY2Joc3EtcmVwb3J0cy9OU0RVSERldGFpbGVkVGFiczIwMThSMi9OU0RVSERldFRhYnNTZWN0MTFwZTIwMTguaHRtIgogIHRhYmxlIDwtIE5TRFVIX3VybCAlPiUKICByZWFkX2h0bWwoKSAlPiUKICBodG1sX25vZGVzKHhwYXRoPVhQQVRIKSAlPiUKICBodG1sX3RhYmxlKCkKICBvdXRwdXQgPC0gdGFibGVbWzFdXQogIG91dHB1dAp9CmBgYAoKTm93IHdlIGNhbiBhcHBseSB0aGUgZnVuY3Rpb24gd2UgY3JlYXRlZCB0byBlYWNoIG9mIHRoZSBYUGF0aHMgZm9yIGVhY2ggb2YgdGhlIHRhYmxlcyBvbiB0aGUgd2Vic2l0ZSB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gdXNlIGluIG91ciBkYXRhIGFuYWx5c2lzLgoKYGBge3J9CnRhYmxlMTEuMWIgPC0gc2NyYXBlcihYUEFUSCA9ICIvaHRtbC9ib2R5L2Rpdls0XS9kaXZbMl0vdGFibGUiKQp0YWJsZTExLjJhIDwtIHNjcmFwZXIoWFBBVEggPSAnL2h0bWwvYm9keS9kaXZbNF0vZGl2WzNdL3RhYmxlJykKdGFibGUxMS4yYiA8LSBzY3JhcGVyKFhQQVRIID0gJy9odG1sL2JvZHkvZGl2WzRdL2Rpdls0XS90YWJsZScpCnRhYmxlMTEuM2EgPC0gc2NyYXBlcihYUEFUSCA9ICcvaHRtbC9ib2R5L2Rpdls0XS9kaXZbNV0vdGFibGUnKQp0YWJsZTExLjNiIDwtIHNjcmFwZXIoWFBBVEggPSAnL2h0bWwvYm9keS9kaXZbNF0vZGl2WzZdL3RhYmxlJykKdGFibGUxMS40YSA8LSBzY3JhcGVyKFhQQVRIID0gJy9odG1sL2JvZHkvZGl2WzRdL2Rpdls3XS90YWJsZScpCnRhYmxlMTEuNGIgPC0gc2NyYXBlcihYUEFUSCA9ICcvaHRtbC9ib2R5L2Rpdls0XS9kaXZbOF0vdGFibGUnKQpgYGAKCgpHcmVhdCEgV2UgaGF2ZSBzdWNjZXNzZnVsbHkgc2NyYXBlZCB0aGUgZGF0YS4KCk5vdyB3ZSBuZWVkIHRvIHdyYW5nbGUgdGhlIGRhdGEuCgoKIyMgKipEYXRhIEV4cGxvcmF0aW9uIGFuZCBXcmFuZ2xpbmcqKgoqKiogCgpOb3cgdGhhdCB3ZSd2ZSBpbXBvcnRlZCB0aGUgZGF0YSwgbGV0J3Mgc2VlIGlmIHdlIGNhbiB3cmFuZ2xlIGEgdGFibGUuIFNpbmNlIHRoZSBkYXRhIGFwcGVhcnMgdG8gYmUgZm9ybWF0dGVkIGluIGEgc2ltaWxhciB3YXkgaW4gZWFjaCBvZiB0aGUgdGFibGVzLCBpdCBpcyBsaWtlbHkgdGhhdCB3aGF0ZXZlciBzdGVwcyB3ZSB0YWtlIHRvIHdyYW5nbGUgdGhpcyBmaXJzdCB0YWJsZSB3aWxsIGFsc28gYmUgbmVjZXNzYXJ5IGluIHRoZSB3cmFuZ2xpbmcgb2Ygc3Vic2VxdWVudCB0YWJsZXMuIFRoaXMgaXMgYmVjYXVzZSB3ZWxsLW1haW50YWluZWQgZGF0YSBzb3VyY2VzIG9mdGVuIGZvcm1hdCBkaWZmZXJlbnQgZGF0YXNldHMgc2ltaWxhcmx5LiBXZSBjYW4gdGFrZSBhZHZhbnRhZ2Ugb2YgdGhpcyBzaW1pbGFyaXR5IHRvIHNwZWVkIHVwIHRoZSB3cmFuZ2xpbmcgcHJvY2Vzcy4gCgojIyMgKipUYWJsZTExLjFhKioKCkZpcnN0IHdlIHdhbnQgdG8gcmVtb3ZlIHRoZSBsYXN0IHJvdyBvZiBvdXIgZGF0YSBmcmFtZSwgd2hpY2ggaGFwcGVucyB0byBiZSB0aGUgbGVnZW5kIG9mIG91ciB0YWJsZS4gUmVjYWxsIGZyb20gbG9va2luZyBhdCB0aGUgd2Vic2l0ZSB0aGF0IHRoZXJlIGlzIGEgbGVnZW5kIGZvciB0aGlzIHRhYmxlLgoKYGBge3IsIGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInRhYmxlMTEuMWEucG5nIikpCmBgYAoKV2UgY2FuIHRha2UgYSBsb29rIGF0IHRoZSBsYXN0IHJvdyB1c2luZyB0aGUgYHRhaWxgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFdlIGNhbiBzcGVjaWZ5IHRoYXQgd2Ugb25seSB3YW50IHRvIHNlZSB0aGUgbGFzdCByb3cgYnkgdXNpbmcgdGhlIGBuID0gMWAgYXJndW1lbnQuCgpgYGB7cn0KdGFibGUxMS4xYSAlPiUKICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lCiAgdGFpbChuID0gMSkKYGBgCgpXZSBjYW4gc2VlIHRoYXQgdGhlIGxlZ2VuZCBpcyByZXBlYXRlZCBmb3IgZXZlcnkgY29sdW1uLiBMZXQncyB0YWtlIGEgbG9vayBhdCB0aGUgeWVhciAyMDA0IGNvbHVtbi4KYGBge3J9CnRhYmxlMTEuMWEgJT4lCiAgZHBseXI6OmFzX3RpYmJsZSgpICU+JSAgCiAgc2VsZWN0KGAyMDA0YCkgJT4lCiAgdGFpbChuID0gMSkKYGBgCgpMZXQncyBzYXZlIHRoaXMgc28gdGhhdCB3ZSBjYW4gcmVmZXIgYmFjayB0byBpdCBsYXRlcjoKYGBge3J9CmxlZ2VuZCA8LSB0YWJsZTExLjFhICU+JQogIGFzX3RpYmJsZSgpICU+JSAgCiAgc2VsZWN0KGAyMDA0YCkgJT4lCiAgdGFpbChuID0gMSkKYGBgCgpBbm90aGVyIHdheSB0byBsb29rIGF0IHRoZSBsYXN0IHJvdyBpcyB0byB1c2UgdGhlIGBuKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFRoaXMgZnVuY3Rpb24gY2FuIGJlIHVzZWQgaW5zaWRlIG90aGVyIGBkcGx5cmAgZnVuY3Rpb25zIGFuZCBpdCBjb3VudHMgdGhlIHRvdGFsIG51bWJlciBvZiBvYnNlcnZhdGlvbnMgb2YgYSBncm91cC4gV2l0aGluIHRoZSBbYHNsaWNlKClgIGZ1bmN0aW9uXShodHRwczovL2RwbHlyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL3NsaWNlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSwgaXQgYWxsb3dzIHlvdSB0byByZWZlciB0aGUgZnVsbCBsZW5ndGggb2YgdGhlIG9iamVjdC4KCmBgYHtyfQp0YWJsZTExLjFhICU+JQogIGRwbHlyOjphc190aWJibGUoKSAlPiUKICBzbGljZShuKCkpIApgYGAKV2UgY2FuIHVzZSB0aGUgYHNsaWNlKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gcmVtb3ZlIHRoaXMgcm93LCBieSB1c2luZyB0aGUgYHNsaWNlYGZ1bmN0aW9uIHRvIHNlbGVjdCBmcm9tIHRoZSBmaXJzdCByb3cgdXNpbmcgYDE6YCB0byB0aGUgc2Vjb25kIHRvIGxhc3Qgcm93IHVzaW5nIGBuKCktMWAuCgpXZSBhcmUgYWxzbyBnb2luZyB0byB1c2UgYSBzcGVjaWFsIHBpcGUgb3BlcmF0b3IgZnJvbSB0aGUgW2BtYWdyaXR0cmAgcGFja2FnZV0oaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvd2ViL3BhY2thZ2VzL21hZ3JpdHRyL3ZpZ25ldHRlcy9tYWdyaXR0ci5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGNhbGxlZCB0aGUgY29tcG91bmQgYXNzaWdubWVudCBwaXBlLW9wZXJhdG9yIG9yIHNvbWV0aW1lcyB0aGUgZG91YmxlIHBpcGUgb3BlcmF0b3IuIFRoaXMgYWxsb3dzIHVzIHRvIHVzZSB0aGUgdGFibGUxMS4xYSBhcyBvdXIgaW5wdXQgYW5kIHJlYXNzaWduIGl0IGF0IHRoZSBlbmQgYWZ0ZXIgYWxsIHRoZSBzdGVwcyBoYXZlIGJlZW4gcGVyZm9ybWVkLgoKV2Ugd2lsbCBhbHNvIGZpcnN0IGNoYW5nZSB0aGUgZGF0YSB0byBiZSBhIFt0aWJibGVdKGh0dHBzOi8vdGliYmxlLnRpZHl2ZXJzZS5vcmcvIzp+OnRleHQ9QSUyMHRpYmJsZSUyQyUyMG9yJTIwdGJsX2RmJTIwJTJDJTIwaXMsbW9kZXJuJTIwcmVpbWFnaW5pbmclMjBvZiUyMHRoZSUyMGRhdGEuJnRleHQ9VGliYmxlcyUyMGFyZSUyMGRhdGEuLGElMjB2YXJpYWJsZSUyMGRvZXMlMjBub3QlMjBleGlzdCkuKSwgd2hpY2ggaXMgdGhlIHRpZHl2ZXJzZSB2ZXJzaW9uIG9mIGEgZGF0YSBmcmFtZSB1c2luZyB0aGUgYGFzX3RpYmJsZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIGFuZCB0aGUgYHRpYmJsZWAgcGFja2FnZS4KCmBgYHtyfQp0YWJsZTExLjFhICU8PiUKICBkcGx5cjo6YXNfdGliYmxlKCkgJT4lCiAgc2xpY2UoMToobigpLTEpKQpgYGAKCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCBkYXRhOgpgYGB7cn0KdGFibGUxMS4xYQpgYGAKCkdyZWF0ISBXZSBjYW4gc2VlIHRoZSB0aGUgbGVnZW5kIGlzIG5vIGxvbmdlciBwYXJ0IG9mIHRoZSBkYXRhLgoKTm93IGxldCdzIHVzZSB0aGUgbGVnZW5kIHRvIHJlY29kZSB0aGUgZGF0YS4gVGhlcmUgYXJlIG1hbnkgZGlmZmVyZW50IHZhbHVlcyBmb3IgbWlzc2luZyBkYXRhLCB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gcmVwbGFjZSB3aXRoIGBOQWAgaW5zdGVhZC4KV2UgY2FuIHVzZSB0aGUgYHB1bGwoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSB0byB0YWtlIGEgbG9vayBhdCB0aGUgbGVnZW5kIGRhdGE6CgpgYGB7cn0KcHVsbChsZWdlbmQsIGAyMDA0YCkKYGBgCgpMb29rcyBsaWtlIHdlIHdhbnQgdG8gcmVwbGFjZSB2YWx1ZXMgdGhhdCBhcmU6IGAqYCwgYC0tYCwgYGRhYCwgYG5jYCwgYW5kIGBucmAuIFdlIGNhbiB1c2UgdGhlIGBuYV9pZigpYCBmdW5jdGlvbiB0byByZWNvZGUgdGhlc2UgdmFsdWVzIHRvIGBOQWAuCgphdm9jYWRvLi4uIHRoZXJlIGlzbid0IHN1cHBvcnQgZm9yIGRvaW5nIHRoaXMgaW4gb25lIGNvbW1hbmQuLi4gYnV0IGNvdWxkIGF0IGxlYXN0IGRvIHR3byBjb21tYW5kcwoKCgpgYGB7cn0KdGFibGUxMS4xYSAlPD4lCiAgZHBseXI6Om5hX2lmKCJuYyIpICU+JQogIGRwbHlyOjpuYV9pZigiLS0iKSAlPiUKICBkcGx5cjo6bmFfaWYoIiIpICU+JQogIGRwbHlyOjpuYV9pZigiKiIpCgp0YWJsZTExLjFhIApgYGAKCk5vdyBsZXQncyByZW5hbWUgdGhlIGZpcnN0IGNvbHVtbiB1c2luZyB0aGUgYHJlbmFtZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBUaGlzIHJlcXVpcmVzIGxpc3RpbmcgdGhlIG5ldyBuYW1lIGZpcnN0IGxpa2Ugc286IGBuZXdfbmFtZSA9IG9sZF9uYW1lYC4KYGBge3J9CnRhYmxlMTEuMWEgJTw+JQogIGRwbHlyOjpyZW5hbWUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgICAgICAgICAgYFNldHRpbmcgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlV2FzIFJlY2VpdmVkYCkKaGVhZCh0YWJsZTExLjFhKQpgYGAKCk5pY2UhCgpOb3cgeW91IG1heSBub3RpY2UgdGhhdCB0aGUgaW5kaXZpZHVhbCB2YWx1ZXMgaGF2ZSBhbiBgImEiYCBhZnRlciB0aGUgbnVtZXJpYyB2YWx1ZS4KCkFjY29yZGluZyB0byB0aGUgbGVnZW5kIHRoaXMgaW5kaWNhdGVzIGlmICJ0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoaXMgZXN0aW1hdGUgYW5kIHRoZSAyMDE4IGVzdGltYXRlIGlzIHNpZ25pZmljYW50IGF0IHRoZSAuMDUgbGV2ZWwuIgoKV2hpbGUgdGhpcyBpcyB1c2VmdWwgaW5mb3JtYXRpb24sIGl0IG1ha2VzIGl0IGRpZmZpY3VsdCB0byB3b3JrIHdpdGggb3VyIG51bWVyaWMgdmFsdWVzLCBzbyB3ZSB3YW50IHRvIHJlbW92ZSB0aGVtLgoKU2luY2UgbG93ZXIgY2FzZSAiYSIgdmFsdWVzIG9jY3VyIGluIHRoZSBmaXJzdCBjb2x1bW4gdmFsdWVzLCB3ZSB3YW50IHRvIG1ha2VzIHN1cmUgd2UgZG9uJ3QgcmVtb3ZlIHRoZXNlLgoKU28gaG93IGNhbiB3ZSBkbyB0aGlzPyBXZSBjYW4gdXNlIHRoZSBgc3RyaW5ncmAgcGFja2FnZSB0byBtb2RpZnkgY2hhcmFjdGVyIHN0cmluZ3MuIGFuZCB3ZSBjYW4gdXNlIHRoZSBgZHBseXJgIGZ1bmN0aW9ucyBgbXV0YXRlKClgLCBgc2VsZWN0KClgIGFuZCBgYWNyb3NzKClgIHRvIHNwZWNpZnkgd2FudCBjb2x1bW5zIHdlIHdhbnQgdG8gY2hhbmdlLgoKQ3VycmVudGx5IGFsbCBvZiBvdXIgZGF0YSBpcyBvZiBjbGFzcyBjaGFyYWN0ZXIgYXMgaW5kaWNhdGVkIGJ5IHRoZSBgPGNocj5gIHVuZGVyIHRoZSBjb2x1bW4gbmFtZXMuIAoKPGRldGFpbHM+IDxzdW1tYXJ5PiBDbGljayBoZXJlIGZvciBhbiBleHBsYW5hdGlvbiBvZiB3aGF0IGEgY2hhcmFjdGVyIHN0cmluZyBpcyA8L3N1bW1hcnk+CgpUaGVyZSBhcmUgc2V2ZXJhbCBjbGFzc2VzIG9mIGRhdGEgaW4gUiBwcm9ncmFtbWluZy4gQ2hhcmFjdGVyIGlzIG9uZSBvZiB0aGVzZSBjbGFzc2VzLiAKQSBjaGFyYWN0ZXIgc3RyaW5nIGlzIGFuIGluZGl2aWR1YWwgZGF0YSB2YWx1ZSBtYWRlIHVwIG9mIGNoYXJhY3RlcnMuIFRoaXMgY2FuIGJlIGEgcGFyYWdyYXBoLCBsaWtlIHRoZSBsZWdlbmQgZm9yIHRoZSB0YWJsZSwgb3IgaXQgY2FuIGJlIGEgc2luZ2xlIGxldHRlciBvciBudW1iZXIgbGlrZSB0aGUgbGV0dGVyIGAiYSJgIG9yIHRoZSBudW1iZXIgYCIzImAuIElmIGRhdGEgaXMgb2YgY2xhc3MgY2hhcmFjdGVyLCB0aGFuIHRoZSBudW1lcmljIHZhbHVlcyB3aWxsIG5vdCBiZSBwcm9jZXNzZWQgbGlrZSBhIG51bWVyaWMgdmFsdWUgaW4gYSBtYXRoZW1hdGljYWwgc2Vuc2UuIElmIHlvdSB3YW50IHlvdXIgbnVtZXJpYyB2YWx1ZXMgdG8gYmUgaW50ZXJwcmV0ZWQgdGhhdCB3YXksIHRoZXkgbmVlZCB0byBiZSBjb252ZXJ0ZWQgdG8gYSBudW1lcmljIGNsYXNzLiBUaGUgb3B0aW9ucyB0eXBpY2FsbHkgdXNlZCBhcmUgaW50ZWdlciAod2hpY2ggaGFzIG5vIGRlY2ltYWwgcGxhY2UpIGFuZCBkb3VibGUgcHJlY2lzaW9uICh3aGljaCBoYXMgYSBkZWNpbWFsIHBsYWNlKS4gCgo8L2RldGFpbHM+CgogIApUaGUgYHN0cmluZ3JgIHBhY2thZ2UgaGFzIGZ1bmN0aW9ucyB0aGF0IGFsbG93IHVzIHRvIHJlcGxhY2UgKHRoZSBgc3RyX3JlcGxhY2UoKWAgZnVuY3Rpb24pIG9yIHJlbW92ZSh0aGUgYHN0cl9yZW1vdmUoKWAgZnVuY3Rpb24pIGNoYXJhY3RlcnMuIAoKVG8gdXNlIHRoZXNlIHdlIG5lZWQgdG8gYmUgYWJsZSB0byBzcGVjaWZ5IHdoYXQgd2Ugd2FudCB0byByZW1vdmUgYW5kIHJlcGxhY2UuIAoKSGVyZSBpcyBhIHBhcnQgb2YgYSBbY2hlYXRzaGVldF0oaHR0cHM6Ly9yc3R1ZGlvLmNvbS9yZXNvdXJjZXMvY2hlYXRzaGVldHMvKXt0YXJnZXQ9Il9ibGFuayJ9IGFib3V0IHN0cmluZyBtYW5pcHVsYXRpb24gZnJvbSBSU3R1ZGlvLgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInJlZ2V4LnBuZyIpKQpgYGAKCldlIGNhbiBzZWUgdGhhdCB3ZSBjYW4gcmVmZXIgdG8gYW55IGRpZ2l0IChzdWNoIGFzIDEsMiwzIGV0Yy4pIGFzIGBbOmRpZ2l0Ol1gLgpXZSBjYW4gYWxzbyBzZWUgdGhhdCB3ZSBjYW4gcmVmZXIgdG8gYW55IHB1bmN0dWF0aW9uIG1hcmsgYXMgYFs6cHVuY3Q6XWAuCkZpbmFsbHksIHdlIHNlZSB0aGF0IHNwYWNlcyBhbmQgdGFicyBjYW4gYmUgcmVmZXJyZWQgdG8gYXMgYFs6Ymxhbms6XWAuCgoKSWYgd2UgdGFrZSBhIGNsb3NlciBsb29rIGF0IHRoZSBmaXJzdCBjb2x1bW4gb2Ygb3VyIHRhYmxlICh1c2luZyB0aGUgYHB1bGwoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZSksIHdlIGNhbiBzZWUgdGhhdCBiZXNpZGVzIHRoZSBgImEiYCB2YWx1ZXMgdGhhdCB3ZSBzZWUgYWRqYWNlbnQgdG8gb3VyIG51bWVyaWMgdmFsdWVzIGluIHRoZSBib2R5IG9mIHRoZSB0YWJsZSwgd2UgYWxzbyBzb21lIGxhcmdlIHdoaXRlIHNwYWNlcywgc29tZSBudW1lcmljIHZhbHVlcywgaW5zdGFuY2VzIG9mIGBcclxuYCwgYXMgd2VsbCBhcyBzb21lIGNvbW1hcyBhbmQgb3RoZXIgcHVuY3R1YXRpb24gbWFya3MuIAoKYGBge3J9CnB1bGwodGFibGUxMS4xYSwgTUhTX3NldHRpbmcpCmBgYAoKCldlIGNhbiB1c2UgdGhlIGBzdHJfcmVtb3ZlX2FsbCgpYCBmdW5jdGlvbiB3aGljaCBpcyBhIHZhcmlhbnQgb2YgdGhlIGBzdHJfcmVtb3ZlKClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RyaW5ncmAgcGFja2FnZSAod2hpY2ggYWxsb3dzIHVzIHRvIHJlbW92ZSBhbGwgb2NjdXJyZW5jZXMgb2Ygc3BlY2lmaWVkIGNoYXJhY3RlcnMgaW4gZWFjaCByb3cgcmF0aGVyIHRoYW4ganVzdCB0aGUgZmlyc3Qgb2NjdXJyZW5jZSwgd2hpY2ggaXMgd2hhdCBgc3RyX3JlbW92ZSgpYCBkb2VzKSwgdG8gcmVtb3ZlIHRoZSBkaWdpdCB2YWx1ZXMsIHRoZSBgXHJcbmAgY2hhcmFjdGVycyBhbmQgdGhlIHB1bmN0dWF0aW9uIG1hcmtzIGZyb20gdGhlIGNvbHVtbiBjYWxsZWQgYE1IU19zZXR0aW5nYC4KClVzaW5nIHRoZSBgbXV0YXRlKClgIGZ1bmN0aW9uIHdlIHNwZWNpZnkgdGhhdCB3ZSB3YW50IHRvIGNoYW5nZSB0aGlzIHBhcnRpY3VsYXIgY29sdW1uIGFuZCByZXBsYWNlIGl0IHdpdGggYSB2ZXJzaW9uIG9mIHRoaXMgY29sdW1uIHRoYXQgaGFzIHJlbW92ZWQgY2hhcmFjdGVycyB0aGF0IG1hdGNoIGRpZ2l0cywgYHJcbmAgb3IgcHVuY3R1YXRpb24gbWFya3MuCgpXZSBuZWVkIHRvIHNwZWNpZnkgdGhhdCB0aGUgY2hhcmFjdGVyIHN0cmluZ3MgdGhhdCBzaG91bGQgYmUgdXNlZCBjYW4gYmUgZm91bmQgaW4gdGhlIGBNSFNfc2V0dGluZ2AgY29sdW1uIGJ5IHVzaW5nIHRoZSBgc3RyaW5nID1gIGFyZ3VtZW50IGFuZCB0aGUgcGF0dGVybnMgdG8gZmluZCBhbmQgcmVtb3ZlIGFyZSBzcGVjaWZpZWQgdXNpbmcgdGhlIGBwYXR0ZXJuID1gIGFyZ3VtZW50LgoKVG8gYWxsb3cgdXMgdG8gbG9vayBmb3IgYWxsIHRocmVlIG9mIHRoZXNlIHBhdHRlcm5zIGF0IHRoZSBzYW1lIHRpbWUsIHdlIGNhbiB1c2UgdGhlIGB8YCBzeW1ib2wgYmV0d2VlbiBlYWNoIHBhdHRlcm4uCgoKYGBge3J9CnRhYmxlMTEuMWEgJTw+JQptdXRhdGUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgc3RyX3JlbW92ZV9hbGwoc3RyaW5nID0gTUhTX3NldHRpbmcsIAogICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiWzpkaWdpdDpdfFxyXG58WzpwdW5jdDpdfCIpKQoKdGFibGUxMS4xYQpgYGAKCldlIGFsc28gd2FudCB0byByZXBsYWNlIHRoZSBzcGFjZXMgd2l0aCBhIHNpbmdsZSBzcGFjZS4gV2UgY2FuIHNlZSB0aGF0IHNvbWV0aW1lcyB0aGVyZSBhcHBlYXJzIHRvIGJlIG1vcmUgdGhhbiBvbmUgc3BhY2UuIFdlIGNhbiBzcGVjaWZ5IHRoYXQgd2Ugd2FudCBhbnkgb2NjdXJyZW5jZSBvZiAxIG9yIG1vcmUgIHRvIGJlIHJlcGxhY2VkIGJ5IHVzaW5nIHRoZSBgezEsfWAgbm90YXRpb24uCgpTZWUgaGVyZSBmb3IgYW4gZXhwbGFuYXRpb24gb2YgdGhpcyBvbiB0aGUgY2hlYXQgc2hlZXQ6CgpgYGB7cn0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgInF1YW50aWZpZXJzLnBuZyIpKQpgYGAKClNvIG5vdyB3ZSB3aWxsIHVzZSB0aGUgYHN0cl9yZXBsYWNlX2FsbCgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UuCkluIHRoaXMgY2FzZSB3ZSBhbHNvIG5lZWQgdG8gc3BlY2lmeSBhIHJlcGxhY2VtZW50IHdpdGggdGhlIGByZXBsYWNlbWVudCA9IGAgYXJndW1lbnQuCgoKCmBgYHtyfSAKdGFibGUxMS4xYSU8PiUKbXV0YXRlKE1IU19zZXR0aW5nID0gCiAgICAgICAgIHN0cl9yZXBsYWNlX2FsbChzdHJpbmcgPSBNSFNfc2V0dGluZywKICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJbOmJsYW5rOl17MSx9IiwgCiAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiICIpKQoKdGFibGUxMS4xYQpgYGAKCk5vdyB0byBmaW5hbGx5IHJlbW92ZSB0aGUgImEiIHZhbHVlcyBhbmQgdGhlIGNvbW1hcyBmcm9tIHRoZSBib2R5IG9mIHRoZSB0YWJsZSB3ZSBjYW4gdXNlIGBzdHJfcmVtb3ZlX2FsbCgpYCBmdW5jdGlvbiB5ZXQgYWdhaW4uIEhvd2V2ZXIgdGhpcyB0aW1lIHRvIHNwZWNpZnkgdGhhdCB3ZSB3YW50IGFsbCBjb2x1bW5zIGV4Y2VwdCB0aGUgZmlyc3QgY29sdW1uIGNhbGxlZCBgTUhTX3NldHRpbmdgLCB3ZSBjYW4gdXNlIHRoZSBgYWNyb3NzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UuIFRoaXMgYWxsb3dzIHVzIHRvIHNwZWNpZnkgd2hhdCBjb2x1bW5zIHdlIHdhbnQgdG8gbXV0YXRlIGJ5IHVzaW5nIHRoZSBgLmNvbHMgPSBgIGFyZ3VtZW50LiBXZSBjYW4gc2VsZWN0IGFsbCBjb2x1bW5zIGV4Y2VwdCB0aGUgZmlyc3QgY29sdW1uIGNhbGxlZCBgTUhTX3NldHRpbmdgIGJ5IHVzaW5nIGEgbWludXMgc2lnbiBgLWAgaW4gZnJvbnQgb2YgdGhlIGNvbHVtbiBuYW1lLgoKCgpgYGB7cn0KdGFibGUxMS4xYSU8PiUKbXV0YXRlKGRwbHlyOjphY3Jvc3MoLmNvbHMgPSAtTUhTX3NldHRpbmcsCiAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVtb3ZlX2FsbCwgImF8LCIpKQoKdGFibGUxMS4xYQpgYGAKCk91ciB0YWJsZSBpcyBsb29raW5nIG11Y2ggYmV0dGVyIQoKV2UgYWxzbyB3YW50IHRvIGNoYW5nZSBvdXIgdmFsdWVzIHRvIGJlIG51bWVyaWMgYXMgb3Bwb3NlZCB0byBjaGFyYWN0ZXIgc28gdGhhdCB3ZSBjYW4gdXNlIHRoZW0gaW4gbWF0aGVtYXRpY2FsIGZ1bmN0aW9ucy4gV2UgY2FuIHVzZSB0aGUgYmFzZSBgYXMubnVtZXJpYygpYCBmdW5jdGlvbi4gQWdhaW4gd2Ugd2lsbCB1c2UgdGhlIGBhY3Jvc3MoKWAgZnVuY3Rpb24gdG8gaW5kaWNhdGUgd2hhdCB2YXJpYWJsZXMgd2Ugd2lzaCB0byBtdXRhdGUuCgpgYGB7cn0KdGFibGUxMS4xYSAlPD4lCiAgbXV0YXRlKGFjcm9zcyguY29scyA9LU1IU19zZXR0aW5nLCBhcy5udW1lcmljKSkKCnRhYmxlMTEuMWEKYGBgCgpXZSB3b3VsZCBhbHNvIGxpa2UgdG8gYWRkIGEgYHR5cGVgIGFuZCBgc3VidHlwZWAgdmFyaWFibGUsIHRoYXQgc3BlY2lmaWVzIHRoZSBnZW5lcmFsIGNhdGVnb3JpZXMgb2Ygc2V0dGluZ3Mgd2hlcmUgc2VydmljZXMgd2VyZSByZWNlaXZlZCwgYXMgd2VsbCBhcyByZW1vdmUgYSBjb3VwbGUgb2Ygcm93cyB0aGF0IGFyZSBjb21wbGV0ZWx5IGVtcHR5LiBUaGVzZSBhcmUgdGhlIHJvd3Mgd2hlcmUgdGhlIGZpcnN0IGNvbHVtbiB2YWx1ZXMgYXJlIGBHZW5lYXJsX01lZGljaW5lYCBhbmQgYEp1dmVuaWxlX0p1c3RpY2VgLCBhbmQgYENoaWxkIFdlbGZhcmVgLiBJZiB3ZSBsb29rIGF0IHRoZSB3ZWJzaXRlLCB3ZSBjYW4gc2VlIHRoYXQgdGhlc2Ugd2VyZSBsZWFkaW5nIGxpbmVzIHdpdGggbm8gZGF0YS4KCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAidGFibGUxMS4xYS5wbmciKSkKYGBgCgpGaXJzdCB3ZSB3aWxsIGFkZCB0aGUgYHR5cGVgIGFuZCBgc3VidHlwZWAgdmFyaWFibGVzIHVzaW5nIHRoZSBgbXV0YXRlYCBmdW5jdGlvbi4KCgpgYGB7cn0KdGFibGUxMS4xYSAlPD4lCiAgbXV0YXRlKHR5cGUgPSBjKHJlcCgiU3BlY2lhbHR5IiwgOSksIHJlcCgiTm9uc3BlY2lhbHR5IiwgMTEpKSkgJT4lCiAgbXV0YXRlKHN1YnR5cGUgPWMoIlNwZWNpYWx0eV90b3RhbCIsIAogICAgICAgICAgICAgICAgICAgIHJlcCgiT3V0cGF0aWVudCIsIDUpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIklucGF0aWVudCIsIDMpLCAKICAgICAgICAgICAgICAgICAgICAiTm9uc3BlY2lhbHR5X3RvdGFsIiwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJFZHVjYXRpb24iLCAzKSwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJHZW5lcmFsX21lZGljaW5lIiwgMiksCiAgICAgICAgICAgICAgICAgICAgcmVwKCJKdXZlbmlsZV9KdXN0aWNlIiwgMiksCiAgICAgICAgICAgICAgICAgICAgcmVwKCJDaGlsZF9XZWxmYXJlIiwgMiksIAogICAgICAgICAgICAgICAgICAgICJjb21iaW5hdGlvbiIpKQoKYGBgCgpXZSBhbHNvIHdhbnQgdG8gYWRkIGEgdmFyaWFibGUgd2l0aCBzaG9ydGVyIG5hbWVzIGZvciBsYWJlbHMgaW4gcGxvdHMgYW5kIHN0YXRpc3RpY2FsIG91dHB1dC4KCmBgYHtyfQp0YWJsZTExLjFhICU8PiUKbXV0YXRlKHNob3J0X2xhYmVsID0gYygiU3BlY2lhbHR5IHRvdGFsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIk91dHBhdGllbnQgdG90YWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAiVGhlcmFwaXN0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIkNsaW5pYyIsIAogICAgICAgICAgICAgICAgICAgICAgICJEYXkgcHJvZ3JhbSIsCiAgICAgICAgICAgICAgICAgICAgICAgIkluLWhvbWUgVGhlcmFwaXN0IiwgCiAgICAgICAgICAgICAgICAgICAgICAgIklucGF0aWVudCB0b3RhbCIsIAogICAgICAgICAgICAgICAgICAgICAgICJIb3NwaXRhbCIsIAogICAgICAgICAgICAgICAgICAgICAgICJSZXNpZGVudGlhbCBDZW50ZXIiLAogICAgICAgICAgICAgICAgICAgICAgICJOb25zcGVjaWFsdHkgdG90YWwiLCAKICAgICAgICAgICAgICAgICAgICAgICAiU2Nob29sIHRvdGFsIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIlNjaG9vbCBUaGVyYXBpc3QiLCAKICAgICAgICAgICAgICAgICAgICAgICAiU2Nob29sIFByb2dyYW0iLCAKICAgICAgICAgICAgICAgICAgICAgICAiR2VuZXJhbCBNZWRpY2luZSIsCiAgICAgICAgICAgICAgICAgICAgICAgIkZhbWlseSBEciIsCiAgICAgICAgICAgICAgICAgICAgICAgIkp1c3RpY2UgU3lzdGVtIiwKICAgICAgICAgICAgICAgICAgICAgICAiSnVzdGljZSBTeXN0ZW0iLAogICAgICAgICAgICAgICAgICAgICAgICJXZWxmYXJlIiwgCiAgICAgICAgICAgICAgICAgICAgICAgIkZvc3RlcmNhcmUiLCAKICAgICAgICAgICAgICAgICAgICAgICAiU3BlY2lhbHR5IENvbWJpbmF0aW9uIikpCmBgYAoKCldlIGNhbiByZW1vdmUgdGhlIGVtcHR5IHJvd3MgdXNpbmcgdGhlIGBmaWx0ZXIoKWAgZnVuY3Rpb24gb2YgdGhlIGBkcGx5cmAgcGFja2FnZS4gV2UgY2FuIHNwZWNpZnkgdGhhdCB3ZSBkb24ndCB3YW50IHRvIGtlZXAgdGhlc2Ugcm93cyBieSB1c2luZyB0aGUgYCE9YCBub3QgZXF1YWwgdG8gb3BlcmF0b3IuIAoKCmBgYHtyfQp0YWJsZTExLjFhICU8PiUKICBkcGx5cjo6ZmlsdGVyKE1IU19zZXR0aW5nICE9ICJHZW5lcmFsX01lZGljaW5lIikgJT4lCiAgZHBseXI6OmZpbHRlcihNSFNfc2V0dGluZyAhPSAiSnV2ZW5pbGVfSnVzdGljZSIpICU+JQogIGRwbHlyOjpmaWx0ZXIoTUhTX3NldHRpbmcgIT0gIkNoaWxkX1dlbGZhcmUiKQoKdGFibGUxMS4xYSAKYGBgCgoKRmluYWxseSwgd2Ugd291bGQgbGlrZSB0byBjaGFuZ2UgdGhlIHNoYXBlIG9mIG91ciB0YWJsZSBzbyB0aGF0IHdlIGhhdmUgYSBuZXcgY29sdW1uIHRoYXQgcmVwcmVzZW50cyB0aGUgeWVhciBhbmQgYSBuZXcgY29sdW1uIHRoYXQgcmVwcmVzZW50cyB0aGUgdmFsdWUgZm9yIHRoYXQgeWVhci4gVG8gZG8gc28gd2Ugd2lsbCBiZSBtYWtpbmcgb3VyIHRhYmxlICJsb25nZXIiLCBtZWFuaW5nIHRoYXQgaXQgd2lsbCBoYXZlIGZld2VyIHJvd3MgYW5kIG1vcmUgY29sdW1ucy4gIFNlZSBbaGVyZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvV2lkZV9hbmRfbmFycm93X2RhdGEpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgZGlmZmVyZW50IHRhYmxlIGZvcm1hdHMsIHR5cGljYWxseSByZWZlcnJlZCB0byBhcyB3aWRlIGFuZCBsb25nIG9yIHNvbWV0aW1lcyBuYXJyb3cuCgpXZSB3aWxsIHVzZSB0aGUgYHBpdm90X2xvbmdlcigpYCBmdW5jdGlvbiBvZiB0aGUgYHRpZHlyYCBwYWNrYWdlIHRvIGNoYW5nZSB0aGUgc2hhcGUgb2Ygb3VyIHRhYmxlLiAKClRoZXJlIGFyZSAzIG1haW4gYXJndW1lbnRzIGluIHRoaXMgZnVuY3Rpb246ICAgCjEpIGNvbHMgLSB3aGljaCBzcGVjaWZpZXMgd2hhdCBjb2x1bW5zIHRvIGNvbGxhcHNlICAKMikgbmFtZXNfdG8gLSB3aGljaCBzcGVjaWZpZXMgdGhlIG5hbWUgb2YgdGhlIG5ldyBjb2x1bW4gdGhhdCB3aWxsIGJlIGNyZWF0ZWQgdGhhdCB3aWxsIGNvbnRhaW4gdGhlIGNvbHVtbiBuYW1lcyBvZiB0aGUgY29sdW1ucyB5b3UgYXJlIGNvbGxhcHNpbmcgIAozKSB2YWx1ZXNfdG8gLSB3aGljaCBzcGVjaWZpZXMgdGhlIG5hbWUgb2YgdGhlIG5ldyBjb2x1bW4gdGhhdCB3aWxsIGJlIGNyZWF0ZWQgdGhhdCB3aWxsIGNvbnRhaW4gdGhlIHZhbHVlcyBmcm9tIHRoZSBjb2x1bW5zIHlvdSBhcmUgY29sbGFwc2luZyAKClRvIHNwZWNpZnkgdGhhdCB3ZSB3YW50IHRvIGNvbGxhcHNlIGFsbCBjb2x1bW5zIGV4Y2VwdCB0aGUgYE1IU19zZXR0aW5nYCBjb2x1bW4gd2UgY2FuIGFnYWluIHVzZSB0aGUgbWludXMgc2lnbi4gRmluYWxseSwgd2Ugd2lsbCBtYWtlIHRoZSBgWWVhcmAgdmFyaWFibGUgbnVtZXJpYyBhcyB3ZWxsLgoKCmBgYHtyfQp0YWJsZTExLjFhICU8PiUKICB0aWR5cjo6cGl2b3RfbG9uZ2VyKGNvbHMgPSBjb250YWlucygiMjAiKSwgCiAgICAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlllYXIiLAogICAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJOdW1iZXIiKSAlPiUKICBtdXRhdGUoWWVhciA9IGFzLm51bWVyaWMoWWVhcikpCgp0YWJsZTExLjFhCmBgYAoKV2UgY2FuIHNlZSB0aGF0IG91ciB0YWJsZSBpcyBub3cgbXVjaCBsb25nZXIgLSBhcyB3ZSBoYXZlIGByIGRpbSh0YWJsZTExLjFhKVsxXWAgcm93cyEKCiMjIyMgey5xdWVzdGlvbl9ibG9ja30KPGI+PHU+IFF1ZXN0aW9uIE9wcG9ydHVuaXR5IDwvdT48L2I+CgpXaHkgZG8gd2UgaGF2ZSBgciBkaW0odGFibGUxMS4xYSlbMV1gIHJvd3Mgbm93PwoKIyMjIwoKTm93IHdlIHNlZSB0aGF0IHRoZSBgWWVhcmAgYW5kIGBOdW1iZXJgIHZhcmlhYmxlcyBhcmUgb2YgY2xhc3MgZG91YmxlIGJlY2F1c2Ugb2YgdGhlIGA8ZGJsPmAgdW5kZXIgdGhlIGNvbHVtbiBuYW1lLgoKTGV0J3MgdGFrZSBhIGxvb2sgYXQgd2hhdCB0aGUgcmVzdCBvZiB0aGUgdGFibGVzIGNvbnRhaW46CgoKVGFibGUgICB8IERldGFpbHMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgCi0tLXwtLS0tLS0tLS0tLS0tClRhYmxlIDExLjFBICAgICAgIHwgU2V0dGluZ3MgV2hlcmUgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBXZXJlIFJlY2VpdmVkIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTc6IE51bWJlcnMgaW4gVGhvdXNhbmRzLCAyMDAyLTIwMTggICAKVGFibGUgMTEuMUIgICAgICAgfCBTZXR0aW5ncyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VzIFdlcmUgUmVjZWl2ZWQgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNzogUGVyY2VudGFnZXMsIDIwMDItMjAxOCAgClRhYmxlIDExLjJBICAgICAgIHwgIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIgYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3LCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IE51bWJlcnMgaW4gVGhvdXNhbmRzLCAyMDA0LTIwMTgKVGFibGUgMTEuMkIgICAgICAgfCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNywgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNC0yMDE4ClRhYmxlIDExLjNBICAgICAgIHwgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIHdpdGggU2V2ZXJlIEltcGFpcm1lbnQgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNywgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBOdW1iZXJzIGluIFRob3VzYW5kcywgMjAwNi0yMDE4ClRhYmxlIDExLjNCICAgICAgIHwgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIHdpdGggU2V2ZXJlIEltcGFpcm1lbnQgaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNywgYnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzOiBQZXJjZW50YWdlcywgMjAwNi0yMDE4ClRhYmxlIDExLjRBICAgICAgIHwgUmVjZWlwdCBvZiBUcmVhdG1lbnQgZm9yIERlcHJlc3Npb24gaW4gUGFzdCBZZWFyIGFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyB3aXRoIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXIsIGJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogTnVtYmVycyBpbiBUaG91c2FuZHMsIDIwMDQtMjAxOApUYWJsZSAxMS40QiAgICAgICB8IFJlY2VpcHQgb2YgVHJlYXRtZW50IGZvciBEZXByZXNzaW9uIGluIFBhc3QgWWVhciBhbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTcgd2l0aCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyLCBieSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3M6IFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgKCk9LLCBzbyB0aGUgbmV4dCB0YWJsZSBpcyB2ZXJ5IHNpbWlsYXIgdG8gVGFibGUxMS4xQSwgd2hpbGUgdGhlIHJlbWFpbmluZyB0YWJsZXMgaGF2ZSBpbmZvcm1hdGlvbiBhYm91dCBkZW1vZ3JhcGhpY3MuCgoKCgpBcyBhIHJlbWluZGVyIGhlcmUgYXJlIGFsbCBvZiB0aGUgc3RlcHMgdGhhdCB3ZSBwZXJmb3JtZWQgdG8gd3JhbmdsZSBgdGFibGUxMS4xYWA6CgoKCmBgYHtyLCBldmFsID0gRkFMU0V9CnRhYmxlMTEuMWEgJTw+JQogIGRwbHlyOjphc190aWJibGUoKSAlPiUKICBzbGljZSgxOihuKCktMSkpJT4lCiAgZHBseXI6Om5hX2lmKCJuYyIpICU+JQogIGRwbHlyOjpuYV9pZigiLS0iKSAlPiUKICBkcGx5cjo6bmFfaWYoIiIpICU+JQogIGRwbHlyOjpuYV9pZigiKiIpJT4lCiAgZHBseXI6OnJlbmFtZShNSFNfc2V0dGluZyA9IAogICAgICAgICAgICAgICAgICBgU2V0dGluZyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VXYXMgUmVjZWl2ZWRgKSAlPiUKICBtdXRhdGUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgc3RyX3JlbW92ZV9hbGwoc3RyaW5nID0gTUhTX3NldHRpbmcsIAogICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiWzpkaWdpdDpdfFxyXG58WzpwdW5jdDpdfCIpKSAlPiUKICBtdXRhdGUoTUhTX3NldHRpbmcgPSAKICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKHN0cmluZyA9IE1IU19zZXR0aW5nLAogICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIls6Ymxhbms6XXsxLH0iLCAKICAgICAgICAgICAgICAgICAgICByZXBsYWNlbWVudCA9ICIgIikpICU+JQogIG11dGF0ZShkcGx5cjo6YWNyb3NzKC5jb2xzID0gLU1IU19zZXR0aW5nLAogICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX3JlbW92ZV9hbGwsICJhfCwiKSkgJT4lCiAgbXV0YXRlKGFjcm9zcygtTUhTX3NldHRpbmcsIGFzLm51bWVyaWMpKSAlPiUKICBtdXRhdGUodHlwZSA9IGMocmVwKCJTcGVjaWFsdHkiLCA5KSwgcmVwKCJOb25zcGVjaWFsdHkiLCAxMSkpKSAlPiUKICBtdXRhdGUoc3VidHlwZSA9YygiU3BlY2lhbHR5X3RvdGFsIiwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJPdXRwYXRpZW50IiwgNSksIAogICAgICAgICAgICAgICAgICAgIHJlcCgiSW5wYXRpZW50IiwgMyksIAogICAgICAgICAgICAgICAgICAgICJOb25zcGVjaWFsdHlfdG90YWwiLCAKICAgICAgICAgICAgICAgICAgICByZXAoIkVkdWNhdGlvbiIsIDMpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIkdlbmVyYWxfbWVkaWNpbmUiLCAyKSwKICAgICAgICAgICAgICAgICAgICByZXAoIkp1dmVuaWxlX0p1c3RpY2UiLCAyKSwKICAgICAgICAgICAgICAgICAgICByZXAoIkNoaWxkX1dlbGZhcmUiLCAyKSwgCiAgICAgICAgICAgICAgICAgICAgImNvbWJpbmF0aW9uIikpICU+JQogIG11dGF0ZShzaG9ydF9sYWJlbCA9IGMoIlNwZWNpYWx0eSB0b3RhbCIsICJPdXRwYXRpZW50IHRvdGFsIiwgIlRoZXJhcGlzdCIsICJDbGluaWMiLCAiRGF5IHByb2dyYW0iLCAiSW4taG9tZSBUaGVyYXBpc3QiLCAiSW5wYXRpZW50IHRvdGFsIiwgIkhvc3BpdGFsIiwgIlJlc2lkZW50aWFsIENlbnRlciIsICJOb25zcGVjaWFsdHkgdG90YWwiLCAiU2Nob29sIHRvdGFsIiwgIlNjaG9vbCBUaGVyYXBpc3QiLCAiU2Nob29sIFByb2dyYW0iLCAiR2VuZXJhbCBNZWRpY2luZSIsICJGYW1pbHkgRHIiLCAiSnVzdGljZSBTeXN0ZW0iLCAiSnVzdGljZSBTeXN0ZW0iLCAiV2VsZmFyZSIsICJGb3N0ZXJjYXJlIiwgIlNwZWNpYWx0eSBDb21iaW5hdGlvbiIpKSAlPiUKICBkcGx5cjo6ZmlsdGVyKE1IU19zZXR0aW5nICE9ICJHZW5lcmFsX01lZGljaW5lIikgJT4lCiAgZHBseXI6OmZpbHRlcihNSFNfc2V0dGluZyAhPSAiSnV2ZW5pbGVfSnVzdGljZSIpICU+JQogIGRwbHlyOjpmaWx0ZXIoTUhTX3NldHRpbmcgIT0gIkNoaWxkX1dlbGZhcmUiKSAlPiUKICAgIHRpZHlyOjpwaXZvdF9sb25nZXIoY29scyA9IGNvbnRhaW5zKCIyMCIpLCAKICAgICAgICAgICAgICAgICAgbmFtZXNfdG8gPSAiWWVhciIsCiAgICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIk51bWJlciIpICU+JQogICBtdXRhdGUoWWVhciA9IGFzLm51bWVyaWMoWWVhcikpCmBgYAoKTm93IHdlIHdhbnQgdG8gd3JhbmdsZSB0YWJsZTExLjFCIHdoaWNoIGlzIGZvcm1hdHRlZCB0aGUgbW9zdCBzaW1pbGFybHkuIFRvIGRvIHNvIHdlIGNhbiBzaW1wbHkgcnVuIHRoZXNlIHN0ZXBzIG9uIHRoZSB1c2luZyB0aGUgYHRhYmxlMTEuMUJgIGFzIHRoZSBpbnB1dC4gRm9yIHRoZSBzYWtlIG9mIGVkdWNhdGlvbiBob3dldmVyLCB3ZSB3aWxsIHNob3cgeW91IGhvdyB5b3UgY291bGQgbWFrZSBhIGZ1bmN0aW9uIGlmIHdlIGhhZCBzZXZlcmFsIG1vcmUgc2ltaWxhciB0YWJsZXMgdG8gd3JhbmdsZS4gVGhpcyB3aWxsIGFsc28gbWFrZSBpdCBlYXNpZXIgdG8gd3JpdGUgYSBmdW5jdGlvbiB0byB3cmFuZ2xlIHRoZSBvdGhlciBkZW1vZ3JhcGhpYyB0YWJsZXMuCgpMYXN0IHRpbWUgd2Ugd3JvdGUgYSBmdW5jdGlvbiBpbiB0aGlzIGNhc2Ugc3R1ZHksIHdlIG9ubHkgaGFkIG9uZSBpbnB1dCBpbiBvdXIgZnVuY3Rpb24uIFRoaXMgdGltZSB3ZSB3aWxsIGhhdmUgc2V2ZXJhbCBpbnB1dHMuIFdlIHdpbGwgaGF2ZSB0aGUgdGFibGUgdGhhdCB3ZSB3YW50IHRvIHdyYW5nbGUgYXMgYFRBQkxFYCwgYSBuZXcgbmFtZSBmb3IgdGhlIGZpcnN0IGNvbHVtbiBjYWxsZWQgYG5ld19jb2xgLCBhbmQgYW4gaW5wdXQgY2FsbGVkIGBwaXZvdF9jb2xgIHdoaWNoIHdpbGwgYmUgdGhlIG5hbWUgb2YgdGhlIGNvbHVtbiB0aGF0IHdpbGwgYmUgY3JlYXRlZCBhZnRlciBwaXZvdGluZyB0aGF0IHdpbGwgdGFrZSB0aGUgdmFsdWVzIGZyb20gZWFjaCBvZiB0aGUgeWVhcnMuCgpXZSB3aWxsIGFsc28gYWRkIGNvZGUgdG8gcmVtb3ZlIGFsbCByb3dzIHRoYXQgaGF2ZSBvbmx5IE5BIHZhbHVlcywgdGhpcyBtZWFucyB3ZSBkb24ndCBuZWVkIHRvIGtub3cgd2hhdCByb3dzIGFoZWFkIG9mIHRpbWUuCgpUbyBkbyB0aGlzIHdlIHdpbGwgdXNlIHRoZSBgZmlsdGVyKClgIGFuZCBgc2VsZWN0KClgIGZ1bmN0aW9ucyBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiAKCldlIHdpbGwgY2FsY3VsYXRlIGEgc3VtIG9mIHRoZSBjb3VudCBvZiBgTkFgIHZhbHVlcyBhY3Jvc3MgdGhlIHJvd3MgZm9yIHRoZSBudW1lcmljIGNvbHVtbnMgKHRoZSBjb2x1bW5zIGZvciBlYWNoIHllYXIpIHVzaW5nIHRoZSBiYXNlIGByb3dTdW1zKClgIGZ1bmN0aW9uLgoKVG8gZG8gdGhpcyB3ZSBmaXJzdCBzZWxlY3QgdGhlIGNvbHVtbnMgdGhhdCBhcmUgbnVtZXJpYyB1c2luZzogYHNlbGVjdCguLCBpcy5udW1lcmljKWAsIHdoZXJlIHRoZSBgLmAgcmVmZXJzIHRvIHRoZSB0YWJsZSBhZnRlciBhbGwgdGhlIHByZXZpb3VzIHdyYW5nbGluZyBzdGVwcyBpbiBvdXIgZnVuY3Rpb24uCgpUaGVuIHdlIGdldCBhIHRydWUgb3IgZmFsc2Ugc3RhdGVtZW50IGFib3V0IHdoaWNoIGNvbHVtbnMgaGF2ZSBgTkFgIHZhbHVlcyB3aXRoIHRoZSBiYXNlIGBpcy5uYSgpYCBmdW5jdGlvbiAodGhpcyByZXF1aXJlcyBudW1lcmljIHZhbHVlcykuCgoKVGhlbiB3ZSBjYWxjdWxhdGUgdGhlIHN1bSB1c2luZyB0aGUgYmFzZSBgcm93U3VtcygpYCBmdW5jdGlvbi4KCgpBbHRvZ2V0aGVyIHRoaXMgbG9va3MgbGlrZSB0aGlzOiBgcm93U3Vtcyhpcy5uYShzZWxlY3QoLiwgaXMubnVtZXJpYykpKWAuCkZpbmFsbHkgd2UgY29tcGFyZSB0aGlzIHRvIHRoZSBudW1iZXIgb2YgY29sdW1ucyB0aGF0IGFyZSBudW1lcmljIGJ5IHVzaW5nOiBgbGVuZ3RoKHNlbGVjdCguLCBpcy5udW1lcmljKSkpYCwgd2l0aCB0aGUgaWRlYSB0aGF0IGlmIHRoZSBudW1iZXIgb2YgYE5BYCB2YWx1ZXMgaXMgbGVzcyB0aGFuIHRoZSBudW1iZXIgb2YgY29sdW1ucyB0aGF0IGNvdWxkIGhhdmUgYE5BYCB2YWx1ZXMsIHRoZW4gd2Uga25vdyBpdCBpcyBub3QgYW4gZW1wdHkgcm93LgogICAgICAgICAgICAgIApOb3RlIHRoYXQgaWYgd2Ugd2VyZSB1c2luZyB0aGUgYHN1bW1hcmlzZSgpYCBvciBgbXV0YXRlKClgIGZ1bmN0aW9uIG9yIHRoZSBgZHBseXJgIHBhY2thZ2UsIHRoZW4gd2UgY291bGQgdXNlIHRoZSBgYWNyb3NzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZHBseXJgIHBhY2thZ2UgdG8gc2VsZWN0IHdoYXQgY29sdW1ucyB3ZSB3YW50ZWQgdG8gdXNlIGluIG91ciBjYWxjdWxhdGlvbi4KCgpgYGB7cn0KZGF0YV9wcmVwX3NldHRpbmdzIDwtIGZ1bmN0aW9uKFRBQkxFLCBuZXdfY29sLCBwaXZvdF9jb2wpewogIGRwbHlyOjphc190aWJibGUoVEFCTEUpICU+JQogIHNsaWNlKDE6KG4oKS0xKSklPiUKICBuYV9pZigibmMiKSAlPiUKICBuYV9pZigiLS0iKSAlPiUKICBuYV9pZigiIikgJT4lCiAgbmFfaWYoIioiKSAlPiUKICAgIHJlbmFtZSh7e25ld19jb2x9fSA6PSBuYW1lcyguKVsxXSkgJT4lCiAgICAgbXV0YXRlKHt7bmV3X2NvbH19IDo9IAogICAgICAgICBzdHJfcmVtb3ZlX2FsbChzdHJpbmcgPSBwdWxsKC4sIHt7bmV3X2NvbH19KSwgCiAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJbOmRpZ2l0Ol18XHJcbnxbOnB1bmN0Ol18IikpICU+JQogIG11dGF0ZSh7e25ld19jb2x9fSA6PSAKICAgICAgICAgc3RyX3JlcGxhY2VfYWxsKHN0cmluZyA9cHVsbCguLCB7e25ld19jb2x9fSksCiAgICAgICAgICAgICAgICAgICAgICAgIHBhdHRlcm4gPSAiWzpibGFuazpdezEsfSIsIAogICAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gIiAiKSkgJT4lCiAgbXV0YXRlKGRwbHlyOjphY3Jvc3MoLmNvbHMgPSAte3tuZXdfY29sfX0sCiAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVtb3ZlX2FsbCwgImF8LCIpKSAlPiUKICAgICBtdXRhdGUoYWNyb3NzKC17e25ld19jb2x9fSwgYXMubnVtZXJpYykpICU+JQogICAgbXV0YXRlKHR5cGUgPSBjKHJlcCgiU3BlY2lhbHR5IiwgOSksIHJlcCgiTm9uc3BlY2lhbHR5IiwgMTEpKSkgJT4lCiAgICAgbXV0YXRlKHN1YnR5cGUgPWMoIlNwZWNpYWx0eV90b3RhbCIsIAogICAgICAgICAgICAgICAgICAgIHJlcCgiT3V0cGF0aWVudCIsIDUpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIklucGF0aWVudCIsIDMpLCAKICAgICAgICAgICAgICAgICAgICAiTm9uc3BlY2lhbHR5X3RvdGFsIiwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJFZHVjYXRpb24iLCAzKSwgCiAgICAgICAgICAgICAgICAgICAgcmVwKCJHZW5lcmFsX21lZGljaW5lIiwgMiksCiAgICAgICAgICAgICAgICAgICAgcmVwKCJKdXZlbmlsZV9KdXN0aWNlIiwgMiksCiAgICAgICAgICAgICAgICAgICAgcmVwKCJDaGlsZF9XZWxmYXJlIiwgMiksIAogICAgICAgICAgICAgICAgICAgICJjb21iaW5hdGlvbiIpKSAlPiUKICAgICAgbXV0YXRlKHNob3J0X2xhYmVsID0gYygiU3BlY2lhbHR5IHRvdGFsIiwgIk91dHBhdGllbnQgdG90YWwiLCAiVGhlcmFwaXN0IiwgIkNsaW5pYyIsICJEYXkgcHJvZ3JhbSIsICJJbi1ob21lIFRoZXJhcGlzdCIsICJJbnBhdGllbnQgdG90YWwiLCAiSG9zcGl0YWwiLCAiUmVzaWRlbnRpYWwgQ2VudGVyIiwgIk5vbnNwZWNpYWx0eSB0b3RhbCIsICJTY2hvb2wgdG90YWwiLCAiU2Nob29sIFRoZXJhcGlzdCIsICJTY2hvb2wgUHJvZ3JhbSIsICJHZW5lcmFsIE1lZGljaW5lIiwgIkZhbWlseSBEciIsICJKdXN0aWNlIFN5c3RlbSIsICJKdXN0aWNlIFN5c3RlbSIsICJXZWxmYXJlIiwgIkZvc3RlcmNhcmUiLCAiU3BlY2lhbHR5IENvbWJpbmF0aW9uIikpICU+JQogICAgIGZpbHRlcihyb3dTdW1zKGlzLm5hKHNlbGVjdCguLCBpcy5udW1lcmljKSkpIDwKICAgICAgICAgICAgICBsZW5ndGgoc2VsZWN0KC4sIGlzLm51bWVyaWMpKSkgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb250YWlucygiMjAiKSwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlllYXIiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gcGl2b3RfY29sKSU+JQogICAgIG11dGF0ZShZZWFyID0gYXMubnVtZXJpYyhZZWFyKSkKfQpgYGAKCk5vdyB3ZSBjYW4gYXBwbHkgdGhlIGZ1bmN0aW9uIHRvIGB0YWJsZTExLjFiYC4KCiMjIyAqKlRhYmxlMTEuMWIqKgoKYGBge3J9CnRhYmxlMTEuMWI8LSBkYXRhX3ByZXBfc2V0dGluZ3MoCiAgICAgICAgICAgICAgICAgICAgVEFCTEUgPSB0YWJsZTExLjFiLAogICAgICAgICAgICAgICAgICBuZXdfY29sID0gIk1IU19zZXR0aW5nIiwKICAgICAgICAgICAgICAgIHBpdm90X2NvbCA9ICJQZXJjZW50IikKCnRhYmxlMTEuMWIKYGBgCgpHcmVhdCEKCldoYXQgYWJvdXQgdGhlIHN1YnNlcXVlbnQgdGFibGVzPwoKIyMjICoqRGVtb2dyYXBoaWMgVGFibGVzKioKCkFsbCBvZiB0aGUgcmVzdCBvZiB0aGUgdGFibGVzIGhhdmUgZGVtb2dyYXBoaWMgaW5mb3JtYXRpb24gYW5kIGhhdmUgdGhpcyBnZW5lcmFsIHN0cnVjdHVyZToKCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcyhoZXJlOjpoZXJlKCJpbWciLCAiZGVtX3RhYmxlLnBuZyIpKQpgYGAKCkluIHRoZXNlIHRhYmxlcyB3ZSBoYXZlIGFnZSBncm91cHMgaW4gb3VyIGZpcnN0IGNvbHVtbiBzbyB3ZSBkb24ndCB3YW50IHRvIHJlbW92ZSBkaWdpdHMgb3IgcHVuY3R1YXRpb24gbWFya3MgYW55bW9yZSBzbyB3ZSBuZWVkIHRvIG1vZGlmeSBvdXIgZnVuY3Rpb24gYSBiaXQgdG8gcmVtb3ZlIHRoYXQgc3RlcC4gCgpXZSBhbHNvIHdhbnQgdG8gYWRkIHRoZSB3b3JkIGBBZ2VgIGFuZCBhbiB1bmRlcnNjb3JlIGluIGZyb250IG9mIHRoZSBhZ2UgZ3JvdXAgbGlzdGVkIGluIHRoZSB0YWJsZXMuIFdlIGNhbiB1c2UgdGhlIGBzdHJfcmVwbGFjZSgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UsIGJlY2F1c2Ugbm93IHdlIHdhbnQgdG8gb25seSByZXBsYWNlIHRoZSBmaXJzdCBpbnN0YW5jZSBvZiBgMWAgd2l0aCBgQWdlXzFgLgoKV2UgYWxzbyBwbGFuIHRvIHJlcGxhY2UgdGhlIGZpcnN0IGNvbHVtbiBuYW1lIHdpdGggYERlbW9ncmFwaGljYCBmb3IgYWxsIG9mIHRoZSB0YWJsZXMuCgpXZSBhbHNvIHdhbnQgdG8gY3JlYXRlIGEgbmV3IHZhcmlhYmxlIHRoYXQgbGlzdCB0aGUgc3ViZ3JvdXBzLgoKV2Ugd2lsbCBhbHNvIHdhbnQgdG8gb25seSB3cmFuZ2xlIHRoZSBkYXRhIHVwIHRvIHRoZSBwb2ludCB0aGF0IHdlIGNoYW5nZSB0aGUgc2hhcGUgb2YgdGhlIGRhdGEsIHNvIHRoYXQgd2UgY2FuIGNoZWNrIGhvdyB0aGUgZGF0YSBsb29rcyBmaXJzdC4KCgpgYGB7cn0KZGF0YV9kZW1fc2V0dGluZ3MgPC0gZnVuY3Rpb24oVEFCTEUpewogIGRwbHlyOjphc190aWJibGUoVEFCTEUpICU+JQogIHNsaWNlKDE6KG4oKS0xKSklPiUKICBuYV9pZigibmMiKSAlPiUKICBuYV9pZigiLS0iKSAlPiUKICBuYV9pZigiIikgJT4lCiAgbmFfaWYoIioiKSAlPiUKICAgIHJlbmFtZShEZW1vZ3JhcGhpYyA6PSBuYW1lcyguKVsxXSkgJT4lCiAgbXV0YXRlKERlbW9ncmFwaGljIDo9IAogICAgICAgICBzdHJfcmVwbGFjZV9hbGwoc3RyaW5nID1wdWxsKC4sIERlbW9ncmFwaGljKSwKICAgICAgICAgICAgICAgICAgICAgICAgcGF0dGVybiA9ICJbOmJsYW5rOl17MSx9IiwgCiAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiICIpKSAlPiUKICBtdXRhdGUoRGVtb2dyYXBoaWMgPSBzdHJfcmVwbGFjZShzdHJpbmcgPSBEZW1vZ3JhcGhpYywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gIjEiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnQgPSAiQWdlXzEiKSkgJT4lCiBtdXRhdGUoc3ViZ3JvdXAgPWMoIlRvdGFsIiwKICAgICAgICAgICAgICAgICAgICByZXAoIkFnZSIsIDQpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIlNleCIsIDMpLCAKICAgICAgICAgICAgICAgICAgICByZXAoIlJhY2UvRXRobmljaXR5IiwgOSkpKSU+JQogIG11dGF0ZShkcGx5cjo6YWNyb3NzKC5jb2xzID0gY29udGFpbnMoIjIwIiksCiAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfcmVtb3ZlX2FsbCwgImF8LCIpKSAlPiUKICAgICBtdXRhdGUoYWNyb3NzKGNvbnRhaW5zKCIyMCIpLCBhcy5udW1lcmljKSkgJT4lCiAgICAgZmlsdGVyKHJvd1N1bXMoaXMubmEoc2VsZWN0KC4sIGlzLm51bWVyaWMpKSkgPAogICAgICAgICAgICAgIGxlbmd0aChzZWxlY3QoLiwgaXMubnVtZXJpYykpKX0KYGBgCgpmcm9tIE1pY2hhZWwKCmBgYHtyLCBldmFsPUZBTFNFLCBlY2hvPUZBTFNFfQpkYXRhX3ByZXBfZGVtIDwtIGZ1bmN0aW9uKFRBQkxFLCBvbGRfY29sLCBuZXdfY29sLCBwaXZvdF9jb2wpewogIFRBQkxFIDwtIFRBQkxFWy1kaW0oVEFCTEUpWzFdLF0KICBUQUJMRSA8LSBUQUJMRSAlPiUKICBuYV9pZigibmMiKSAlPiUKICBuYV9pZigiLS0iKSAlPiUKICBuYV9pZigiIikgJT4lCiAgbmFfaWYoIioiKQogIFRBQkxFIDwtIFRBQkxFICU+JQogICAgYXNfdGliYmxlKCkgJT4lCiAgICByZW5hbWUoe3tuZXdfY29sfX0gOj0ge3tvbGRfY29sfX0pCiAgcGFydEEgPC0gVEFCTEUgJT4lCiAgICBkcGx5cjo6c2VsZWN0KHt7bmV3X2NvbH19KQogIHBhcnRCIDwtIFRBQkxFICU+JQogICAgZHBseXI6OnNlbGVjdCgte3tuZXdfY29sfX0pCiAgcGFydEEgPC0gcGFydEEgJT4lCiAgbXV0YXRlKHt7bmV3X2NvbH19IDo9IHBhcnRBICU+JQogICAgICAgICAgIGRwbHlyOjpzZWxlY3Qoe3tuZXdfY29sfX0pICU+JQogICAgICAgICAgIHB1bGwoe3tuZXdfY29sfX0pICU+JQogICAgICAgICAgIGdzdWIoIltcclxuXXxbWzpwdW5jdDpdXXwoW1s6Ymxhbms6XV0pXFwxKyIsCiAgICAgICAgICAgICAgICAgICAgICAgICIiLCAuKSkKICBwYXJ0QSA8LSBwYXJ0QSAlPiUKICBtdXRhdGUoe3tuZXdfY29sfX0gOj0gZHBseXI6OmNhc2Vfd2hlbihzdHJpbmdyOjpzdHJfZGV0ZWN0KCEhYmFzZTo6YXMubmFtZShuZXdfY29sKSwgcGF0dGVybiA9ICIxIikgfiBiYXNlOjpwYXN0ZSgiQWdlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJpbmdyOjpzdHJfc3ViKCEhYmFzZTo6YXMubmFtZShuZXdfY29sKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0ID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9MiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyaW5ncjo6c3RyX3N1YighIWJhc2U6OmFzLm5hbWUobmV3X2NvbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdGFydCA9IDMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSA0KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZXA9Il8iKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+ICEhYmFzZTo6YXMubmFtZShuZXdfY29sKSkpCiAgcGFydEIgPC0gcGFydEIgJT4lCiAgICBtdXRhdGUoYWNyb3NzKC5jb2xzID0gZXZlcnl0aGluZygpLAogICAgICAgICAgICAgICAgc3RyX3JlbW92ZV9hbGwsICJhIikpICU+JQogICAgbXV0YXRlKGFjcm9zcyguY29scyA9IGV2ZXJ5dGhpbmcoKSwKICAgICAgICAgICAgICAgIHN0cl9yZW1vdmVfYWxsLCAiLCIpKQogIHJtKFRBQkxFKQogIFRBQkxFIDwtIGJpbmRfY29scyhwYXJ0QSwKICAgICAgICAgICAgICAgICAgICAgcGFydEIpCiAgVEFCTEUgPC0gVEFCTEUgJT4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb250YWlucygiMjAiKSwgbmFtZXNfdG8gPSAiWWVhciIsIHZhbHVlc190byA9IHBpdm90X2NvbCkKICBUQUJMRQp9CmBgYAoKV2UgdXNlIHRoZSBmdW5jdGlvbiB0byB3cmFuZ2xlIHRoZSBuZXh0IHNldCBvZiB0YWJsZXMuIFdlIHdpbGwgYWxzbyBhZGQgYSBjb2x1bW4gdG8gZGVzY3JpYmUgd2hhdCB0aGUgZGF0YSBpcyBhYm91dCB3aGljaCB3aWxsIGJlIGhlbHBmdWwgZm9yIG1lcmdpbmcgdGhlIGRhdGEgbGF0ZXIuCmBgYHtyfQp0YWJsZTExLjJhIDwtIGRhdGFfZGVtX3NldHRpbmdzKFRBQkxFID0gdGFibGUxMS4yYSkKdGFibGUxMS4yYSAlPD4lIG11dGF0ZShkYXRhX3R5cGUgPSAiTWFqb3JfRGVwcmVzc2l2ZV9FcGlzb2RlIikKZ2xpbXBzZSh0YWJsZTExLjJhKQoKdGFibGUxMS4yYiA8LSBkYXRhX2RlbV9zZXR0aW5ncyhUQUJMRSA9IHRhYmxlMTEuMmIpCnRhYmxlMTEuMmIgJTw+JSBtdXRhdGUoZGF0YV90eXBlID0gIk1ham9yX0RlcHJlc3NpdmVfRXBpc29kZSIpCmdsaW1wc2UodGFibGUxMS4yYikKCnRhYmxlMTEuM2EgPC0gZGF0YV9kZW1fc2V0dGluZ3MoVEFCTEUgPSB0YWJsZTExLjNhKQp0YWJsZTExLjNhICU8PiUgbXV0YXRlKGRhdGFfdHlwZSA9ICJTZXZlcmVfTWFqb3JfRGVwcmVzc2l2ZV9FcGlzb2RlIikKZ2xpbXBzZSh0YWJsZTExLjNhKQoKdGFibGUxMS4zYiA8LSBkYXRhX2RlbV9zZXR0aW5ncyhUQUJMRSA9IHRhYmxlMTEuM2IpCnRhYmxlMTEuM2IgJTw+JSBtdXRhdGUoZGF0YV90eXBlID0gIlNldmVyZV9NYWpvcl9EZXByZXNzaXZlX0VwaXNvZGUiKQpnbGltcHNlKHRhYmxlMTEuM2IpCgp0YWJsZTExLjRhIDwtIGRhdGFfZGVtX3NldHRpbmdzKFRBQkxFID0gdGFibGUxMS40YSkKdGFibGUxMS40YSAlPD4lIG11dGF0ZShkYXRhX3R5cGUgPSAidHJlYXRtZW50IikKZ2xpbXBzZSh0YWJsZTExLjRhKQoKdGFibGUxMS40YiA8LSBkYXRhX2RlbV9zZXR0aW5ncyhUQUJMRSA9IHRhYmxlMTEuNGIpCnRhYmxlMTEuNGIgJTw+JSBtdXRhdGUoZGF0YV90eXBlID0gInRyZWF0bWVudCIpCmdsaW1wc2UodGFibGUxMS40YikKCmBgYAoKR3JlYXQhIEFsbCBvZiB0aGUgZGVtb2dyYXBoaWMgdGFibGVzIGxvb2sgZ29vZC4KCk5vdyBsZXQncyBjb21iaW5lIHRoZSBjb3VudCBkYXRhICh0aGUgImEiIHRhYmxlcykgYW5kIHRoZSBwZXJjZW50IGRhdGEgKHRoZSAiYiIgdGFibGVzKSB1c2luZyB0aGUgYGJpbmRfcm93cygpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlLiBXaGljaCB3aWxsIGFwcGVuZCBlYWNoIG9mIHRoZSBzdWJzZXF1ZW50IHRhYmxlcyB0b2dldGhlci4KCldlIGNhbiB1c2UgdGhlIGBkaXN0aW5jdCgpYCBmdW5jdGlvbiBvZiB0aGUgYGRwbHlyYCBwYWNrYWdlIHRvIGNoZWNrIHRoYXQgd2UgaW5kZWVkIGhhdmUgYWxsIHRoZSBkYXRhIHR5cGVzIG5vdyBpbiB0aGVzZSBsYXJnZXIgdGliYmxlcy4KCmBgYHtyfQpjb3VudHMgPC1iaW5kX3Jvd3ModGFibGUxMS4yYSwgdGFibGUxMS4zYSwgdGFibGUxMS40YSkKcGVyY2VudHMgPC1iaW5kX3Jvd3ModGFibGUxMS4yYiwgdGFibGUxMS4zYiwgdGFibGUxMS40YikKCmNvdW50cyAlPiVkaXN0aW5jdChkYXRhX3R5cGUpCnBlcmNlbnRzICU+JWRpc3RpbmN0KGRhdGFfdHlwZSkKYGBgCkdyZWF0IQoKTm93IHdlIHdpbGwgcmVmb3JtYXQgYm90aCB0aGUgYGNvdW50c2AgYW5kIGBwZXJjZW50c2AgZGF0YSB0byBiZSBpbiB0aGUgbG9uZyBmb3JtYXQgdXNpbmcgYHBpdm90X2xvbmdlcigpYCBvbmNlIGFnYWluLgoKYGBge3J9CmNvdW50cyAlPD4lCiAgcGl2b3RfbG9uZ2VyKGNvbHMgPSBjb250YWlucygiMjAiKSwgCiAgICAgICAgICAgICAgIG5hbWVzX3RvID0gIlllYXIiLCAKICAgICAgICAgICAgICAgdmFsdWVzX3RvID0gIk51bWJlciIpJT4lCiAgICAgbXV0YXRlKFllYXIgPSBhcy5udW1lcmljKFllYXIpKQoKcGVyY2VudHMgJTw+JQogIHBpdm90X2xvbmdlcihjb2xzID0gY29udGFpbnMoIjIwIiksIAogICAgICAgICAgICAgICBuYW1lc190byA9ICJZZWFyIiwgCiAgICAgICAgICAgICAgIHZhbHVlc190byA9ICJQZXJjZW50IiklPiUKICAgICBtdXRhdGUoWWVhciA9IGFzLm51bWVyaWMoWWVhcikpCmBgYAoKTm93IHRoYXQgd2UndmUgd3JhbmdsZWQgdGhlIGRhdGEsIHdlIGNhbiBnbyBhaGVhZCBhbmQgcHJvY2VlZCB3aXRoIG91ciBhbmFseXNpcy4gCgpgYGB7ciwgZXZhbCA9IEZBTFNFLCBlY2hvID0gRkFMU0V9CnNhdmUocGVyY2VudHMsIGNvdW50cywgdGFibGUxMS4xYSwgdGFibGUxMS4xYiwgZmlsZSA9IGhlcmU6OmhlcmUoImRhdGEiLCAid3JhbmdsZWRfZGF0YS5yZGEiKSkKYGBgCgojIyAqKkRhdGEgQW5hbHlzaXMqKgoqKiogCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpsb2FkKGZpbGUgPSBoZXJlOjpoZXJlKCJkYXRhIiwgIndyYW5nbGVkX2RhdGEucmRhIikpCmBgYApSZWNhbGwgd2hhdCBvdXIgbWFpbiBxdWVzdGlvbnMgd2VyZToKCiMjIyMgey5tYWluX3F1ZXN0aW9uX2Jsb2NrfQo8Yj48dT4gT3VyIG1haW4gcXVlc3Rpb25zOiA8L3U+PC9iPgoKMSkgSG93IGhhdmUgZGVwcmVzc2lvbiByYXRlcyBpbiBBbWVyaWNhbiB5b3V0aCBjaGFuZ2VkIHNpbmNlIDIwMDQsIGFjY29yZGluZyB0byB0aGUgTlNEVUggZGF0YT8gIEhvdyBoYXZlIHJhdGVzIGRpZmZlcmVkIGJldHdlZW4gZGlmZmVyZW50IHlvdXRoIHN1Ymdyb3VwcyAoYWdlLCBnZW5kZXIsIGV0aG5pY2l0eSk/CjIpIERvIG1lbnRhbCBoZWFsdGggc2VydmljZXMgYXBwZWFyIHRvIGJlIHJlYWNoaW5nIG1vcmUgeW91dGhzPyBBZ2FpbiwgaG93IGhhdmUgcmF0ZXMgZGlmZmVyZWQgYmV0d2VlbiBkaWZmZXJlbnQgeW91dGggc3ViZ3JvdXBzIChhZ2UsIGdlbmRlciwgZXRobmljaXR5KT8KCgojIyMjCgpXZSBhcmUgc3BlY2lmaWNhbGx5IGludGVyZXN0ZWQgaW4gaG93IHRoZSBmcmVxdWVuY3kgb2YgcmVjZW50IG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZXMgYW1vbmcgeW91dGhzIGRpZmZlciBjb21wYXJlZCB0byB0aG9zZSBpbiAyMDA0LiBXZSBhcmUgYWxzbyBpbnRlcmVzdGVkIGhvdyBkaWZmZXJlbnQgZ3JvdXBzIGRpZmZlci4gV2Ugd2lsbCBzdGFydCB3aXRoIGV4YW1pbmluZyBob3cgbWFsZSBhbmQgZmVtYWxlcyBkaWZmZXIgYWNyb3NzIHRpbWUuCgpTaW5jZSB3ZSBoYXZlIGNvdW50cyBmb3IgdGhlIHR3byBzZXhlczogbWFsZXMgYW5kIGZlbWFsZXMsIGFuZCBmb3IgdGhlIHR3byB5ZWFycyBvZiBpbnRlcmVzdCwgMjAwNCBhbmQgMjAxOCwgd2UgY2FuIGNvbmR1Y3QgYSBbUGVhcnNvbidzIGNoaS1zcXVhcmVkIHRlc3RdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BlYXJzb24lMjdzX2NoaS1zcXVhcmVkX3Rlc3QjOn46dGV4dD1QZWFyc29uJ3MlMjBjaGklMkRzcXVhcmVkJTIwdGVzdCUyMGlzLGRpZmZlcnMlMjBmcm9tJTIwYSUyMHRoZW9yZXRpY2FsJTIwZGlzdHJpYnV0aW9uLil7dGFyZ2V0PSJfYmxhbmsifSBmb3IgaW5kZXBlbmRlbmNlLCB3aGljaCBpcyBhbHNvIHdyaXR0ZW4gbGlrZSB0aGlzOiAke1xjaGl9XjIkLiAKClRoaXMgd2lsbCBhbGxvdyB1cyB0byBjb21wYXJlIGlmIHRoZSBmcmVxdWVuY2llcyBvZiBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGVzIGRpZmZlcnMgZnJvbSB3aGF0IHdlIHdvdWxkIGV4cGVjdCBieSBjaGFuY2UgaWYgdGhlIHZhcmlhYmxlcyB5ZWFycyBhbmQgc2V4IHdlcmUgaW5kZXBlbmRlbnQuCgpUaGUgbnVsbCBoeXBvdGhlc2lzIGlzIHRoYXQgdGhlIHZhcmlhYmxlcyBhcmUgaW5kZXBlbmRlbnQgb3IgdGhhdCB0aGUgIGRpZmZlcmVuY2UgaW4gdGhlIHByb3BvcnRpb25zIGlzIGVxdWFsIHRvIHplcm8uIFRodXMgd2Ugd2FudCB0byB0ZXN0IGlmIHNleCBhbmQgeWVhciBhcmUgaW5kZXBlbmRlbnQuIEluIG90aGVyIHdvcmRzLCB3ZSB3YW50IHRvIGtub3cgaWYgc2V4IGluZmx1ZW5jZXMgdGhlIG51bWJlciBvZiBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGVzIGluIDIwMDQgYW5kIDIwMTguIE9yIHN0YXRlZCB5ZXQgYW5vdGhlciB3YXksIEFyZSBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUgY291bnRzIGFjcm9zcyB0aGUgdHdvIHllYXJzIGFzc29jaWF0ZWQgd2l0aCBzZXguICAKCgoKQWNjb3JkaW5nIHRvIFt3aWtpcGVkaWFdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NoaS1zcXVhcmVkX3Rlc3Q/b2xkZm9ybWF0PXRydWUpe3RhcmdldD0iX2JsYW5rIn06IAoKPiBQZWFyc29uJ3MgY2hpLXNxdWFyZSB0ZXN0IGlzIHVzZWQgdG8gZGV0ZXJtaW5lIHdoZXRoZXIgdGhlcmUgaXMgYSBzdGF0aXN0aWNhbGx5IHNpZ25pZmljYW50IGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgKipleHBlY3RlZCBmcmVxdWVuY2llcyoqIGFuZCB0aGUgKipvYnNlcnZlZCBmcmVxdWVuY2llcyoqIGluIG9uZSBvciBtb3JlICoqY2F0ZWdvcmllcyoqIG9mIGEgW2NvbnRpbmdlbmN5IHRhYmxlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db250aW5nZW5jeV90YWJsZSl7dGFyZ2V0PSJfYmxhbmsifS4KCgpUaHVzLCB0byBjb25kdWN0IHRoaXMgc3RhdGlzdGljYWwgdGVzdCwgd2UgbmVlZCB0byBwcm9kdWNlIGEgW2NvbnRpbmdlbmN5IHRhYmxlXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Db250aW5nZW5jeV90YWJsZSl7dGFyZ2V0PSJfYmxhbmsifSwgd2hpY2ggaW4gdGhpcyBjYXNlIGNvdWxkIGFsc28gYmUgY2FsbGVkIGEgMngyIHRhYmxlLCB3aGljaCBpcyB0aGUgc2ltcGxlc3Qga2luZCBvZiBjb250aW5nZW5jeSB0YWJsZSAob25seSB0d28gbGV2ZWxzIGZvciB0d28gdmFyaWFibGVzKS4KCkhlcmUgaXMgYW4gZXhhbXBsZSBvZiBhbm90aGVyIDJ4MiB0YWJsZToKCgpgYGB7ciwgZWNobyA9IEZBTFNFfQpjb250aWcgPC10aWJibGUoU2V4ID0gYygiTWFsZSIsICJGZW1hbGUiLCAiVG90YWwiKSwgUmlnaHRoYW5kZWQgPSBjKDQxLDQ3LDg4KSwgTGVmdGhhbmRlZCA9IGMoOSwzLCAxMiksIFRvdGFsID0gYyg1MCw1MCwxMDApKQoKY29udGlnCmBgYAoKSGVyZSBhcmUgYWxsIHRoZSBvYnNlcnZlZCB2YWx1ZXMuCgpXZSBjYW4gc2VlIHRoYXQgdGhlcmUgYXJlIHR3byB2YXJpYWJsZXM6IFNleCBhbmQgSGFuZGVkbmVzcyBhbmQgZWFjaCBoYXZlIHR3byBsZXZlbHMgKG1hbGUgYW5kIGZlbWFsZSBmb3Igc2V4IGFuZCByaWdodCBhbmQgbGVmdCBmb3IgaGFuZGVkbmVzcykuIFRoZSB0YWJsZSBhbHNvIGluY2x1ZGVzIHRvdGFscyBvZiBlYWNoIG9mIHRoZSA0IHBvc3NpYmxlIGdyb3VwcyBhcyB3ZWxsIGFzIHRoZSBvdmVyYWxsIHRvdGFsLgoKCk5vdyBsZXQncyBjcmVhdGUgYSB0YWJsZSBvZiBleHBlY3RlZCB2YWx1ZXMgYXNzdW1pbmcgc2V4IGFuZCBoYW5kZWRuZXNzIGFyZSBpbmRlcGVuZGVudC4gCgpUaGUgdG90YWwgcmlnaHQtaGFuZGVkIGlzIDg4IG91dCBvZiAxMDAgd2hpY2ggaXMgZXF1YWwgdG8gODglLgpUaGUgdG90YWwgbGVmdC1oYW5kZWQgaXMgMTIgIG91dCBvZiAxMDAgd2hpY2ggaXMgZXF1YWwgdG8gMTIlLgoKVGh1cyBpZiBlYWNoIHNleCBoYWQgdGhlIHNhbWUgYW1vdW50IG9mIHJpZ2h0LWhhbmRlZG5lc3MgYW5kIGxlZnQtaGFuZGVkbmVzcywgd2Ugd291bGQgZXhwZWN0IDg4JSBvZiB0aGUgbWFsZXMgdG8gYmUgcmlnaHQtaGFuZGVkIGFuZCAxMiAlIHRvIGJlIGxlZnQtaGFuZGVkOyBhbmQKd2Ugd291bGQgZXhwZWN0IHRoZSBleGFjdCBzYW1lIHByb3BvcnRpb25zIG9mIDg4JSByaWdodC1oYW5kZWQgYW5kIDEyJSBsZWZ0LWhhbmRlZCBmb3IgdGhlIGZlbWFsZXMuCgpTaW5jZSB3ZSBoYXZlIDUwIG1hbGVzIGFuZCA1MCBmZW1hbGVzIGFuZCAxMiUgb2YgNTAgaXMgNiBhbmQgODglIG9mIDUwIGlzIDQ0LCB3ZSB3b3VsZCB0aHVzIGhhdmUgdGhlIGZvbGxvd2luZyB0YWJsZSBvZiBleHBlY3RlZCBmcmVxdWVuY2llczoKCmBgYHtyLCBlY2hvID0gRkFMU0V9CmNvbnRpZyA8LXRpYmJsZShTZXggPSBjKCJNYWxlIiwgIkZlbWFsZSIsICJUb3RhbCIpLCBSaWdodGhhbmRlZCA9IGMoNDQsNDQsODgpLCBMZWZ0aGFuZGVkID0gYyg2LDYsIDEyKSwgVG90YWwgPSBjKDUwLDUwLDEwMCkpCgpjb250aWcKCmBgYAoKClRoZSAke1xjaGl9XjIkICBpcyBjYWxjdWxhdGVkIGxpa2Ugc286CgokJHtcY2hpfV4yPVxzdW1fe2o9MX1ee219IFxmcmFjeyhPX2ogLSBFX2opXjJ9e0Vfan0kJAoKV2hlcmUgJE9faiA9IGpee3RofSQgb2JzZXJ2ZWQgY291bnQgYW5kICRFX2ogPSBqXnt0aH0kIGV4cGVjdGVkIGNvdW50IGZvcgp0aGUganRoIGNlbGwgb2YgYSBjb250aW5nZW5jeSB0YWJsZSB3aXRoICRtJCBjZWxscy4KClRoZSBkZWdyZWVzIG9mIGZyZWVkb20gKCRkZiQpIGlzIGNhbGN1bGF0ZWQgbGlrZSBzbzogJGRmPSAoci0xKShjLTEpJC4KCldoZXJlICRyJCA9ICMgb2Ygcm93cyBhbmQgJGMkID0gdGhlICMgb2YgY29sdW1ucy4KCgpTbyB0byBjYWxjdWxhdGUgdGhlICR7XGNoaX1eMiQgZm9yIGhhbmRlZG5lc3MgYW5kIHNleCBtYW51YWxseSwgd2UgY2FuIGRvIHRoZSBmb2xsb3dpbmcgZm9yIGVhY2ggb2YgdGhlIGZvdXIgdmFsdWVzIGluIHRoZSB0YWJsZSAoYmVzaWRlcyB0aGUgdG90YWxzKSBsaWtlIHRoaXM6Cgoke1xjaGl9XjIkID0gZnJhY3Rpb24gb2YgdGhlIHNxdWFyZSBkaWZmZXJlbmNlIG9mIHRoZSBvYnNlcnZlZCBtaW51cyB0aGUgZXhwZWN0ZWQsIGRpdmlkZWQgYnkgZXhwZWN0ZWQgZm9yIHJpZ2h0LWhhbmRlZCBtYWxlcyArIHRoZSBzYW1lIGZvciBsZWZ0LWhhbmRlZCBtYWxlcyArIHRoZSBzYW1lIGZvciByaWdodC1oYW5kZWQgZmVtYWxlcyArIHRoZSBzYW1lIGZvciBsZWZ0LWhhbmRlZCBmZW1hbGVzCgpUaGlzIGlzIGVxdWFsIHRvIDoKCiQke1xjaGl9XjIgPSAgXGZyYWN7KDQxLTQ0KV4yfXs0NH0gKyBcZnJhY3soOS02KV4yfXs2fSsgXGZyYWN7KDQ3LTQ0KV4yfXs0NH0rIFxmcmFjeygzLTYpXjJ9ezZ9JCQKCldoaWNoIGlzIGVxdWFsIHRvOgoKJHtcY2hpfV4yJCA9IGByICgoNDEtNDQpXjIpLzQ0ICsoKDktNileMikvNiArICgoNDctNDQpXjIpLzQ0ICsgKDMtNileMi82YAoKV2hlcmUgdGhlIGRlZ3JlZXMgb2YgZnJlZWRvbSAgPSAkZGYgPSA5Mi0xKSgyLTEpID0gMSQKCgpXaGF0IGRvZXMgdGhpcyBtZWFuPyBXZSBuZWVkIHRvIGNvbnN1bHQgYSBjaGktc3F1YXJlIGRpc3RyaWJ1dGlvbiB0byBkZXRlcm1pbmUgd2hhdCB0aGUgcC12YWx1ZSBpcyBhbmQgaWYgdGhpcyBpcyBzaWduaWZpY2FudC4KCmBgYHtyfQprbml0cjo6aW5jbHVkZV9ncmFwaGljcygiaHR0cHM6Ly91cGxvYWQud2lraW1lZGlhLm9yZy93aWtpcGVkaWEvY29tbW9ucy84LzhlL0NoaS1zcXVhcmVfZGlzdHJpYnV0aW9uQ0RGLUVuZ2xpc2gucG5nIikKYGBgCiMjIyMgW1tzb3VyY2VdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NoaS1zcXVhcmVkX3Rlc3QjL21lZGlhL0ZpbGU6Q2hpLXNxdWFyZV9kaXN0cmlidXRpb25DREYtRW5nbGlzaC5wbmcpe3RhcmdldD0iX2JsYW5rIn0KClRoaXMgW3dlYnNpdGVdKGh0dHA6Ly9ob21lcGFnZS5kaXZtcy51aW93YS5lZHUvfm1ib2duYXIvYXBwbGV0cy9jaGlzcS5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9IGhhcyBhIHNpbXBsZSB3YXkgdG8gY2hlY2sgdGhpcywgd2l0aG91dCByZXF1aXJpbmcgeW91IHRvIGdldCBvdXQgYSBydWxlciBhbmQgY29uc3VsdCB0aGlzIHBsb3QuIE5vdGUgb24gdGhpcyB3ZWJzaXRlIHRoZSBub3RhdGlvbiBmb3IgJGRmJCBpcyAke1xudX0kLgoKUGx1Z2dpbmcgaW4gMy40MDkwOTEgYXMgJHtcY2hpfV4yJCBhbmQgMSBhcyAke1xudX0kLCB3ZSBnZXQgYSAkcC12YWx1ZSQgb2YgMC4wNjQ4NC4KClRodXMgd2UgZG8gbm90IGhhdmUgZW5vdWdoIGV2aWRlbmNlIHRvIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLiAgVGhlcmVmb3JlLCB3ZSBjb25jbHVkZSB0aGF0IHNleCBhbmQgaGFuZGVkbmVzcyBkbyBhcHBlYXIgdG8gYmUgaW5kZXBlbmRlbnQuCgpTZWUgaGVyZSBmb3IgYSBtb3JlIHRob3JvdWdoIGV4cGxhbmF0aW9uIG9mIHRoZSBbY2hpLXNxdWFyZSB0ZXN0XShodHRwczovL3d3dy5saW5nLnVwZW5uLmVkdS9+Y2xpZ2h0L2NoaXNxdWFyZWQuaHRtKXt0YXJnZXQ9Il9ibGFuayJ9LgoKCgpOb3cgbGV0J3MgY3JlYXRlIGEgY29udGluZ2VuY3kgdGFibGUgd2l0aCBvdXIgb3duIGRhdGEgYW5kIHNlZSBob3cgd2UgY2FuIGltcGxlbWVudCB0aGlzIHRlc3QgaW4gUi4KCkl0IGlzIGNyaXRpY2FsIHRoYXQgd2UgdXNlIHRoZSBjb3VudHMgZGF0YSwgYW5kIG5vdCB0aGUgcGVyY2VudGFnZSBkYXRhIGZvciBvdXIgYW5hbHlzaXMsIGFzIHRoZSAke1xjaGl9XjIkIHJlcXVpcmVzIGNvdW50cy4gCgoKV2Ugd2lsbCBmaWx0ZXIgdGhlIGNvdW50IGRhdGEgZm9yIHRoZSBgTWFqb3JfRGVwcmVzc2l2ZV9FcGlzb2RlYCBkYXRhLCBhcyB3ZWxsIGFzIGZvciB0aGUgYE1hbGVgIGFuZCBgRmVtYWxlYCBkYXRhIGZyb20gYDIwMDRgIGFuZCBgMjAxOGAuCgoKVGhlIGZvbGxvd2luZyBjb2RlIHN1YnNldHMgdGhlIGRhdGEgd2UgbmVlZCBhbmQgbWFrZXMgdGhlIG5lY2Vzc2FyeSBtYW5pcHVsYXRpb25zIHNvIHRoYXQgdGhlIHVuaXRzIG9mIG9ic2VydmF0aW9uIGFyZSBhcHByb3ByaWF0ZS4gSWYgd2UgdGFrZSBhIGxvb2sgYXQgdGhlIHRpdGxlIG9mIHRoZSB0YWJsZSB3ZSBjYW4gc2VlIHRoYXQgdGhlIG51bWJlcnMgaW4gdGhlIHRhYmxlIHJlcHJlc2VudCBpbmRpdmlkdWFscyBieSB0aGUgdGhvdXNhbmRzLgoKYGBge3J9CmtuaXRyOjppbmNsdWRlX2dyYXBoaWNzKGhlcmU6OmhlcmUoImltZyIsICJkZW1fdGFibGUucG5nIikpCmBgYAoKYGBge3J9CmNoaV9zcXVhcmVfMTEuMmEgPC0gY291bnRzICU+JQogIGZpbHRlcihkYXRhX3R5cGUgPT0gIk1ham9yX0RlcHJlc3NpdmVfRXBpc29kZSIpJT4lCiAgZmlsdGVyKFllYXIgJWluJSBjKDIwMDQsIDIwMTgpKSAlPiUKICBmaWx0ZXIoRGVtb2dyYXBoaWMgJWluJSBjKCJNYWxlIiwiRmVtYWxlIikpICU+JQogIG11dGF0ZShOdW1iZXIgPSBOdW1iZXIgKiAxMDAwKQpgYGAKClRoZSByZXN1bHRpbmcgb2JqZWN0IGNvbnRhaW5zIGFsbCB0aGUgdmFsdWVzIHdlIG5lZWQgZm9yIG91dCBjb250aW5nZW5jeSB0YWJsZS4gCgpgYGB7cn0KY2hpX3NxdWFyZV8xMS4yYQpgYGAKCiAKCkEgY29udGluZ2VuY3kgdGFibGUgY2FuICBub3cgYmUgcHJvZHVjZWQgZnJvbSB0aGlzIGRhdGEgd2hpY2ggaXMgaW4gbG9uZyBmb3JtYXQgYnkgdHJhbnNmb3JtaW5nIHRoZSBkYXRhIHRvIHdpZGUgZm9ybWF0IGFuZCByZS1wdXJwb3Npbmcgc29tZSB2YWx1ZXMgYXMgcm93IG5hbWVzLiBUbyByZWZvcm1hdCB0aGUgZGF0YSB0byB3aWRlIGZvcm1hdCB3ZSBjYW4gdXNlIHRoZSBgcGl2b3Rfd2lkZXIoKWAgZnVuY3Rpb24gb2YgdGhlIGB0aWR5cmAgcGFja2FnZS4KCkZvciB0aGlzIGZ1bmN0aW9uIHRoZXJlIGFyZSBzZXZlcmFsIGltcG9ydGFudCBhcmd1bWVudHM6ICAKMSkgbmFtZXNfZnJvbSAtIHRoaXMgaXMgdGhlIHZhcmlhYmxlIHdoZXJlIHRoZSBuYW1lcyBvZiBuZXcgY29sdW1ucyB3aWxsIGNvbWUgZnJvbQoyKSB2YWx1ZXNfZnJvbSAtIHRoaXMgaXMgdGhlIHZhcmlhYmxlIHdoZXJlIHRoZSB2YWx1ZXMgZm9yIHRoZSBuZXcgY29sdW1ucyB3aWxsIGNvbWUgZnJvbQozKSBuYW1lc19wcmVmaXggLSBpZiB3ZSB3YW50IHRvIGFkZCBhIHByZWZpeCB0byB0aGUgbmV3IGNvbHVtbnMgd2UgY2FuIGRvIHNvIHVzaW5nIHRoaXMgYXJndW1lbnQKClNvIGluIG91ciBjYXNlIHdlIHdhbnQgdG8gc3ByZWFkIG91dCB0aGUgeWVhciBkYXRhIGludG8gdHdvIGNvbHVtbnMgdGh1cyB0aGUgbmFtZXMgd2lsbCBjb21lIGZyb20gdGhlIGBZZWFyYCB2YXJpYWJsZSBhbmQgdGhlIHZhbHVlcyB3aWxsIGNvbWUgZnJvbSB0aGUgYE51bWJlcmAgdmFyaWFibGUuIFdlIHdhbnQgdG8gYWRkIHRoZSB3b3JkIGBZZWFyYCB0byB0aGUgbmV3IGNvbHVtbnMuIFdlIGFsc28gd2FudCB0aGUgcmVtb3ZlIHRoZSBgc3ViZ3JvdXBgIGFuZCBgZGF0YV90eXBlYCB2YXJpYWJsZXMgYW5kIG9ubHkga2VlcCB0aGUgYERlbW9ncmFwaGljYCwgYFllYXJgLCBhbmQgYE51bWJlcmAgdmFyaWFibGVzLiBUbyBkbyBzbyB3ZSBjYW4gdXNlIHRoZSBgc2VsZWN0KClgIGZ1bmN0aW9uLiBGaW4KCmBgYHtyfQpjaGlfc3F1YXJlXzExLjJhICU8PiUKICBzZWxlY3QoRGVtb2dyYXBoaWMsIFllYXIsIE51bWJlcikgJT4lCiAgdGlkeXI6OnBpdm90X3dpZGVyKAogICAgICAgICAgICAgICAgICAgICBuYW1lc19mcm9tID0gWWVhciwKICAgICAgICAgICAgICBuYW1lc19wcmVmaXggPSAiWWVhciIsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gTnVtYmVyKQpjaGlfc3F1YXJlXzExLjJhCgpgYGAKCk5vdyB3ZSBjYW4gdXNlIHRoZSBgY29sdW1uX3RvX3Jvd25hbWVzKClgIGZ1bmN0aW9uIG9mIHRoZSBgdGliYmxlYCBwYWNrYWdlIHRvIG1ha2UgdGhlIGBEZW1vZ3JhcGhpY2AgdmFyaWFibGUgbGV2ZWxzIHRoZSByb3cgbmFtZXMuIE90aGVyd2lzZSB3ZSB3b3VsZCBuZWVkIHRvIHNlbGVjdCB0aGUgbnVtZXJpYyBjb2x1bW5zIHRvIHBlcmZvcm0gdGhlIHN0YXRzIHRlc3QuCgpgYGB7cn0KY2hpX3NxdWFyZV8xMS4yYSAlPD4lCiAgdGliYmxlOjpjb2x1bW5fdG9fcm93bmFtZXMoIkRlbW9ncmFwaGljIikKCmNoaV9zcXVhcmVfMTEuMmEKYGBgCgpOb3RlIHRoYXQgYSBjb250aW5nZW5jeSB0YWJsZSB3b3VsZCBhbHNvIGhhdmUgdG90YWxzIGZvciBhbGwgZ3JvdXBzIGFzIHdlbGwsIGJ1dCB0aGlzIGlzIG5vdCBuZWNlc3NhcnkgZm9yIHRoZSBgc3RhdHM6OmNoaXNxLnRlc3QoKWAgZnVuY3Rpb24uCgoKVGhlIGNoaS1zcXVhcmVkIHRlc3QgZm9yIGluZGVwZW5kZW5jZSBjYW4gYmUgY29uZHVjdGVkIHVzaW5nIHRoZSBgc3RhdHM6OmNoaXNxLnRlc3QoKWAgZnVuY3Rpb24uIAoKYGBge3J9CnN0YXRzOjpjaGlzcS50ZXN0KGNoaV9zcXVhcmVfMTEuMmEpCmBgYAoKV2Ugc2VlIHRoYXQgdGhlIHAtdmFsdWUgaXMgdmVyeSBzbWFsbCwgd2hpY2ggc3VnZ2VzdHMgdGhhdCBzZXggZG9lcyBpbmZsdWVuY2UgdGhlIGNvdW50IG9mIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZXMgYWNyb3NzIHRpbWUuIAoKSG93IGFib3V0IGZvciBzZXZlcmUgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2Rlcz8KCgpgYGB7cn0KY2hpX3NxdWFyZV8xMS4zYSA8LSBjb3VudHMgJT4lCiAgZmlsdGVyKGRhdGFfdHlwZSA9PSAiU2V2ZXJlX01ham9yX0RlcHJlc3NpdmVfRXBpc29kZSIpJT4lCiAgZmlsdGVyKFllYXIgJWluJSBjKDIwMDksIDIwMTgpKSAlPiUKICBmaWx0ZXIoRGVtb2dyYXBoaWMgJWluJSBjKCJNYWxlIiwiRmVtYWxlIikpICU+JQogIG11dGF0ZShOdW1iZXIgPSBOdW1iZXIgKiAxMDAwKQoKY2hpX3NxdWFyZV8xMS4zYSA8LSBjaGlfc3F1YXJlXzExLjNhICU+JQogIHNlbGVjdCgtZGF0YV90eXBlKSAlPiUKICBzZWxlY3QoLXN1Ymdyb3VwKSAlPiUKICBwaXZvdF93aWRlcihuYW1lc19mcm9tID0gWWVhciwKICAgICAgICAgICAgICBuYW1lc19wcmVmaXggPSAiWWVhciIsIAogICAgICAgICAgICAgIHZhbHVlc19mcm9tID0gTnVtYmVyKSAlPiUKICBjb2x1bW5fdG9fcm93bmFtZXMoIkRlbW9ncmFwaGljIikKCmNoaV9zcXVhcmVfMTEuM2EKYGBgCgpgYGB7cn0KY2hpc3EudGVzdChjaGlfc3F1YXJlXzExLjNhKQpgYGAKVGhlcmUgYWxzbyBhcHBlYXJzIHRvIGJlIGFuIGluZmx1ZW5jZSBvZiBzZXggb24gdGhlIHJhdGUgb2Ygc2V2ZXJlIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZXMgYWNyb3NzIHRoZSB5ZWFycy4KCgpIb3cgYWJvdXQgdHJlYXRtZW50PwoKCmBgYHtyfQpjaGlfc3F1YXJlXzExLjRhIDwtIGNvdW50cyAlPiUKICBmaWx0ZXIoZGF0YV90eXBlID09ICJ0cmVhdG1lbnQiKSU+JQogIGZpbHRlcihZZWFyICVpbiUgYygyMDA5LCAyMDE4KSkgJT4lCiAgZmlsdGVyKERlbW9ncmFwaGljICVpbiUgYygiTWFsZSIsIkZlbWFsZSIpKSAlPiUKICBtdXRhdGUoTnVtYmVyID0gTnVtYmVyICogMTAwMCkKCmNoaV9zcXVhcmVfMTEuNGEgPC0gY2hpX3NxdWFyZV8xMS40YSAlPiUKICBzZWxlY3QoLWRhdGFfdHlwZSkgJT4lCiAgc2VsZWN0KC1zdWJncm91cCkgJT4lCiAgcGl2b3Rfd2lkZXIobmFtZXNfZnJvbSA9IFllYXIsCiAgICAgICAgICAgICAgbmFtZXNfcHJlZml4ID0gIlllYXIiLCAKICAgICAgICAgICAgICB2YWx1ZXNfZnJvbSA9IE51bWJlcikgJT4lCiAgY29sdW1uX3RvX3Jvd25hbWVzKCJEZW1vZ3JhcGhpYyIpCgpjaGlfc3F1YXJlXzExLjRhCmBgYAoKYGBge3J9CmNoaXNxLnRlc3QoY2hpX3NxdWFyZV8xMS40YSkKYGBgClRoZXJlIGFsc28gYXBwZWFycyB0byBiZSBhbiBpbmZsdWVuY2Ugb2Ygc2V4IG9uIHRoZSByYXRlIGF0IHdoaWNoIHlvdXRocyByZWNlaXZlZCB0cmVhdG1lbnQgYWNyb3NzIHRoZSB0d28geWVhcnMuCgoKYXZvY2Fkby4uIEkgdGhpbmsgaXQgbWFrZXMgc2Vuc2UgdG8gbW92ZSB0aGUgdmlzdWFsaXphdGlvbiBzZWN0aW9uIGZpcnN0Li4uIGFuZCB1c2UgaXQgdG8gbW90aXZhdGUgdGhhdCBhbmFseXNpcyBmcm9tIHRoZSB5ZWFyIDIwMTAgYW5kIG9mIG1hbGUgYW5kIGZlbWFsZXMuLi4KCiMjICoqRGF0YSBWaXN1YWxpemF0aW9uKioKKioqIAoKYGBge3IsIGVjaG8gPSBGQUxTRX0KbG9hZChmaWxlID0gaGVyZTo6aGVyZSgiZGF0YSIsICJ3cmFuZ2xlZF9kYXRhLnJkYSIpKQpgYGAKCk9LLCBzbyBub3cgd2UgYXJlIGdvaW5nIHRvIG1ha2Ugc29tZSB2aXN1YWxpemF0aW9ucyB0byBmdXJ0aGVyIGV4cGxvcmUgb3VyIHF1ZXN0aW9ucyBvZiBpbnRlcmVzdC4KCldlIGFyZSBnb2luZyB0byB1c2UgdGhlIGBnZ3Bsb3QyYCBwYWNrYWdlIHRvIGNyZWF0ZSBvdXIgcGxvdHMuCgo8ZGV0YWlscz48c3VtbWFyeT4gQ2xpY2sgaGVyZSBmb3IgYW4gaW50cm9kdWN0aW9uIGFib3V0IHRoaXMgcGFja2FnZSBpZiB5b3UgYXJlICBuZXcgdG8gdXNpbmcgYGdncGxvdDJgIDwvc3VtbWFyeT4KClRoZSBbZ2dwbG90MiBwYWNrYWdlXShodHRwOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnKSBpcyBnZW5lcmFsbHkgaW50dWl0aXZlIGZvciBiZWdpbm5lcnMgYmVjYXVzZSBpdCBpcyBiYXNlZCBvbiBhICBbZ3JhbW1hciBvZiBncmFwaGljc10oaHR0cDovL3ZpdGEuaGFkLmNvLm56L3BhcGVycy9sYXllcmVkLWdyYW1tYXIuaHRtbCkgb3IgdGhlIGBnZ2AgaW4gYGdncGxvdDJgLiBUaGUgaWRlYSBpcyB0aGF0IHlvdSBjYW4gY29uc3RydWN0IG1hbnkgc2VudGVuY2VzIGJ5IGxlYXJuaW5nIGp1c3QgYSBmZXcgbm91bnMsIGFkamVjdGl2ZXMsIGFuZCB2ZXJicy4gVGhlcmUgYXJlIHNwZWNpZmljIOKAnHdvcmRz4oCdIHRoYXQgd2Ugd2lsbCBuZWVkIHRvIGxlYXJuIGFuZCBvbmNlIHdlIGRvLCB5b3Ugd2lsbCBiZSBhYmxlIHRvIGNyZWF0ZSAob3Ig4oCcd3JpdGXigJ0pIGh1bmRyZWRzIG9mIGRpZmZlcmVudCBwbG90cy4KClRoZSBjcml0aWNhbCBwYXJ0IHRvIG1ha2luZyBncmFwaGljcyB1c2luZyBgZ2dwbG90MmAgaXMgdGhlIGRhdGEgbmVlZHMgdG8gYmUgaW4gYSBfdGlkeV8gZm9ybWF0LiAKR2l2ZW4gdGhhdCB3ZSBoYXZlIGp1c3Qgc3BlbnQgdGltZSBwdXR0aW5nIG91ciBkYXRhIGluIF90aWR5XyBmb3JtYXQsIHdlIGFyZSBwcmltZWQgdG8gdGFrZSBhZHZhbnRhZ2Ugb2YgYWxsIHRoYXQgYGdncGxvdDJgIGhhcyB0byBvZmZlciEgCgpXZSB3aWxsIHNob3cgaG93IGl0IGlzIGVhc3kgdG8gcGlwZSBfdGlkeV8gZGF0YSAob3V0cHV0KSBhcyBpbnB1dCB0byBvdGhlciBmdW5jdGlvbnMgdGhhdCBjcmVhdGUgcGxvdHMuIApUaGlzIGFsbCB3b3JrcyBiZWNhdXNlIHdlIGFyZSB3b3JraW5nIAp3aXRoaW4gdGhlIF90aWR5dmVyc2VfLiAKCgoqKldoYXQgaXMgdGhlIGBnZ3Bsb3QoKWAgZnVuY3Rpb24/KiogCkFzIGV4cGxhaW5lZCBieSBIYWRsZXkgV2lja2hhbToKCj4gVGhlIGdyYW1tYXIgdGVsbHMgdXMgdGhhdCBhIHN0YXRpc3RpY2FsIGdyYXBoaWMgaXMgYSBtYXBwaW5nIGZyb20gZGF0YSB0byBhZXN0aGV0aWMgYXR0cmlidXRlcyAoY29sb3VyLCBzaGFwZSwgc2l6ZSkgb2YgZ2VvbWV0cmljIG9iamVjdHMgKHBvaW50cywgbGluZXMsIGJhcnMpLiBUaGUgcGxvdCBtYXkgYWxzbyBjb250YWluIHN0YXRpc3RpY2FsIHRyYW5zZm9ybWF0aW9ucyBvZiB0aGUgZGF0YSBhbmQgaXMgZHJhd24gb24gYSBzcGVjaWZpYyBjb29yZGluYXRlcyBzeXN0ZW0uCgogYGdncGxvdDJgIFRlcm1pbm9sb2d5IAoqICoqZ2dwbG90KiogLSB0aGUgbWFpbiBmdW5jdGlvbiB3aGVyZSB5b3Ugc3BlY2lmeSB0aGUgZGF0YXNldCBhbmQgdmFyaWFibGVzIHRvIHBsb3QgKHRoaXMgaXMgd2hlcmUgd2UgZGVmaW5lIHRoZSBgeGAgYW5kCmB5YCB2YXJpYWJsZSBuYW1lcykKKiAqKmdlb21zKiogLSBnZW9tZXRyaWMgb2JqZWN0cwogICAgKiBlLmcuIGBnZW9tX3BvaW50KClgLCBgZ2VvbV9iYXIoKWAsIGBnZW9tX2xpbmUoKWAsIGBnZW9tX2hpc3RvZ3JhbSgpYAoqICoqYWVzKiogLSBhZXN0aGV0aWNzCiAgICAqIHNoYXBlLCB0cmFuc3BhcmVuY3ksIGNvbG9yLCBmaWxsLCBsaW5lIHR5cGVzCiogKipzY2FsZXMqKiAtIGRlZmluZSBob3cgeW91ciBkYXRhIHdpbGwgYmUgcGxvdHRlZAogICAgKiBjb250aW51b3VzLCBkaXNjcmV0ZSwgbG9nLCBldGMKClRoZSBmdW5jdGlvbiBgYWVzKClgIGlzIGFuIGFlc3RoZXRpYyBtYXBwaW5nIGZ1bmN0aW9uIGluc2lkZSB0aGUgYGdncGxvdCgpYCBvYmplY3QuIApXZSB1c2UgdGhpcyBmdW5jdGlvbiB0byBzcGVjaWZ5IHBsb3QgYXR0cmlidXRlcyAoZS5nLiBgeGAgYW5kIGB5YCB2YXJpYWJsZSBuYW1lcykgdGhhdCB3aWxsIG5vdCBjaGFuZ2UgYXMgd2UgYWRkIG1vcmUgbGF5ZXJzLiAgCgpBbnl0aGluZyB0aGF0IGdvZXMgaW4gdGhlIGBnZ3Bsb3QoKWAgb2JqZWN0IGJlY29tZXMgYSBnbG9iYWwgc2V0dGluZy4gCkZyb20gdGhlcmUsIHdlIHVzZSB0aGUgYGdlb21gIG9iamVjdHMgdG8gYWRkIG1vcmUgbGF5ZXJzIHRvIHRoZSBiYXNlIGBnZ3Bsb3QoKWAgb2JqZWN0LiAKVGhlc2Ugd2lsbCBkZWZpbmUgd2hhdCB3ZSBhcmUgaW50ZXJlc3RlZCBpbiBpbGx1c3RyYXRpbmcgdXNpbmcgdGhlIGRhdGEuCgo8L2RldGFpbHM+CgojIyMgTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlcyBpbiBwYXN0IHllYXIKCldlIHdpbGwgc3RhcnQgYnkgdGFraW5nIGEgbG9vayBhdCB0aGUgcmF0ZSBvZiBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGVzIGFtb25nIHlvdXRocyBvdmVyIHRpbWUgb2YgdGhlIHZhcmlvdXMgZGVtb2dyYXBoaWMgZ3JvdXBzLgoKT0ssIHdlIHdpbGwgc3RhcnQgb3V0IGJ5IHVzaW5nIHRoZSBgZ2dwbG90KClgIGZ1bmN0aW9uIHRvIHNwZWNpZnkgd2hhdCBkYXRhIHdlIHdvdWxkIGxpa2UgdG8gcGxvdCBvbiBlYWNoIGF4aXMuIFdlIHdpbGwgYWxzbyBpbmRpY2F0ZSB0aGF0IHdvdWxkIGxpa2UgdG8gdXNlIHRoZSBgRGVtb2dyYXBoaWNgIHZhcmlhYmxlIHRvIGdyb3VwIG91ciBkYXRhIGFuZCB0byBjb2xvciBvdXIgZGF0YS4gIFRoaXMgaXMgb3VyIGZpcnN0IGxheWVyIG9mIHRoZSBwbG90LCB0aHVzIGZvciBzdWJzZXF1ZW50IGxheWVycyB3ZSBuZWVkIHRvIHVzZSBhIHBsdXMgc2lnbiBgK2AuIAoKTmV4dCB3ZSB3aWxsIHVzZSB0aGUgYGdlb21fbGluZSgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UgdG8gc3BlY2lmeSB0aGF0IHdlIHdvdWxkIGxpa2UgdG8gY3JlYXRlIGEgbGluZSBwbG90LiAKClRoZW4gd2Ugd2lsbCBhZGQgbGFiZWxzIGZvciB0aGUgdGl0bGUgYW5kIHN1YnRpdGxlIHVzaW5nIHRoZSBgbGFicygpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UuIAoKRmluYWxseSB3ZSB3aWxsIG1vdmUgb3VyIGxlZ2VuZCB0byB0aGUgYm90dG9tIG9mIHRoZSBwbG90IHVzaW5nIHRoZSBgdGhlbWUoKWAgZnVuY3Rpb24gd2hpY2ggaGVscHMgdXMgY29udHJvbCB2YXJpb3VzIGRldGFpbHMgYWJvdXQgb3VyIHBsb3QuIAoKYGBge3J9CnBlcmNlbnRzICU+JQogICAgZmlsdGVyKGRhdGFfdHlwZSA9PSAiTWFqb3JfRGVwcmVzc2l2ZV9FcGlzb2RlIiklPiUKZ2dwbG90Mjo6Z2dwbG90KGFlcyh4ID0gWWVhciwgCiAgICAgICAgICAgICAgICAgICAgeSA9IFBlcmNlbnQsIAogICAgICAgICAgICAgICAgZ3JvdXAgPSBEZW1vZ3JhcGhpYywgCiAgICAgICAgICAgICAgICBjb2xvciA9IERlbW9ncmFwaGljKSkrCiAgZ2VvbV9saW5lKHNpemUgPSAxKSArCiAgbGFicyh0aXRsZSA9ICJNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzLCBQZXJjZW50YWdlcywgMjAwNC0yMDE4IikgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iKQpgYGAKIFRoaXMgcGxvdCB2ZXJ5IGRpZmZpY3VsdCB0byByZWFkIGJlY2F1c2UgdGhlcmUgYXJlIHNvIHZlcnkgbWFueSBncm91cHMuIApOb3cgbGV0J3MgbG9vayBhdCBqdXN0IHRoZSB0b3RhbCBhY3Jvc3MgdGltZS4gV2UgY2FuIGRvIHNvIGJ5IGZpcnN0IGZpbHRlcmluZyBvdXIgZGF0YSBmb3IgdG90YWwgdmFsdWVzLiAKCkl0IHdvdWxkIGFsc28gbmljZSB0byBpbmNsdWRlIGV2ZXJ5IHllYXIgaW4gdGhlIHgtYXhpcy4gV2UgY2FuIGRvIHNvIGJ5IHVzaW5nIHRoZSBgc2NhbGVfeF9jb250aW51b3VzKClgIGZ1bmN0aW9uIHdoaWNoIGdpdmVzIHVzIGdyZWF0ZXIgY29udHJvbCBhYm91dCBob3cgdGhlIHgtYXhpcyBpcyBkaXNwbGF5ZWQuCgpGaW5hbGx5LCB3ZSB3aWxsIGRyb3AgdGhlIGxlZ2VuZCBzaW5jZSB3ZSB3aWxsIG9ubHkgaGF2ZSBvbmUgZ3JvdXAgdXNpbmcgYGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lImAgYW5kIHdlIGNhbiBjaGFuZ2UgdGhlIGFuZ2xlIG9mIHRoZSB4LWF4aXMgdGV4dCB1c2luZyBgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MClgIHdpdGhpbiB0aGUgYHRoZW1lKClgIGZ1bmN0aW9uLgoKV2Ugd2lsbCBhbHNvIG1ha2UgdGhlIGxpbmUgdGhpY2tlciB1c2luZyB0aGUgYHNpemUgPWAgYXJndW1lbnQgZm9yIHRoZSBgZ2VvbV9saW5lKClgIGZ1bmN0aW9uLgoKVGhlIGB0aGVtZV9saW5lZHJhdygpYCBmdW5jdGlvbiBjaGFuZ2VzIHRoZSBhZXN0aGV0aWNzIG9mIHRoZSBwbG90LiBTZWUgW2hlcmVdKGh0dHBzOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnL3JlZmVyZW5jZS9nZ3RoZW1lLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIGEgbGlzdCBvZiBvcHRpb25zLgoKYGBge3J9Ck1ERV90b3RhbCA8LXBlcmNlbnRzICU+JQogIGZpbHRlcihkYXRhX3R5cGUgPT0gIk1ham9yX0RlcHJlc3NpdmVfRXBpc29kZSIpJT4lCiAgZmlsdGVyKERlbW9ncmFwaGljID09ICJUT1RBTCIpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIAogICAgICAgICAgICAgeSA9IFBlcmNlbnQsIAogICAgICAgICBncm91cCA9IERlbW9ncmFwaGljLCAKICAgICAgICAgY29sb3IgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX2xpbmUoYWVzKGNvbG9yID0gRGVtb2dyYXBoaWMpLCBzaXplID0gMS41KSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDQsIDIwMTgpKSArCiAgbGFicyh0aXRsZSA9ICJQZXJjZW50IG9mIFBlcnNvbnMgQWdlZCAxMiB0byAxNyBSZXBvcnRpbmcgSGF2aW5nIGEgXG4gTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIHRoZSBQYXN0IFllYXIgIikrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIAoKTURFX3RvdGFsCmBgYAoKV2UgY2FuIHNlZSB0aGF0IHRoZXJlIGlzIGEgc3RlZXAgaW5jcmVhc2UgYWZ0ZXIgYXJvdW5kIDIwMTE6CgpMZXQncyBhZGQgYSBkaWZmZXJlbnQgYmFja2dyb3VuZCBjb2xvciBmb3IgdGhlIHllYXJzIHNpbmNlIDIwMTEuCldlIGNhbiBkbyBzbyBieSBhZGRpbmcgYSBgZ2VvbV9yZWN0KClgIGxheWVyIGJlZm9yZSB3ZSBwbG90IHRoZSBsaW5lLgpXZSBqdXN0IG5lZWQgdG8gc3BlY2lmeSB0aGUgbG9jYXRpb24gb2YgdGhlIHJlY3RhbmdsZSBvbiBvdXIgcGxvdC4KCmBgYHtyfQpNREVfdG90YWwgPC1wZXJjZW50cyAlPiUKICBmaWx0ZXIoZGF0YV90eXBlID09ICJNYWpvcl9EZXByZXNzaXZlX0VwaXNvZGUiKSU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyA9PSAiVE9UQUwiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gUGVyY2VudCwgZ3JvdXAgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX3JlY3QoeG1pbiA9IDIwMTEsIHhtYXggPSBJbmYsICAKICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsICAKICAgICAgICAgICAgZmlsbCA9ICJsaWdodCBncmF5IikrCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IERlbW9ncmFwaGljKSwgc2l6ZSA9IDEuNSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA0LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiVGhlIFJhdGUgb2YgWW91dGhzIEFnZWQgMTIgdG8gMTcgUmVwb3J0aW5nIEhhdmluZyBhIFxuIE1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiB0aGUgUGFzdCBZZWFyIGlzIEluY3JlYXNpbmciKSsKICB0aGVtZV9jbGFzc2ljKCkrCiAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiKSAKCk1ERV90b3RhbAoKYGBgCgpOb3cgbGV0J3MgbG9vayBhdCBncm91cCBkaWZmZXJlbmNlcy4gIAoKVG8gbWFrZSBzdXJlIG91ciBwbG90IGlzIG5vdCB0b28gb3ZlcndoZWxtaW5nLCBsZXQncyBsaW1pdCB0byBvbmx5IGFnZSBhbmQgc2V4IHN1Ymdyb3Vwcy4gVGh1cyB3ZSB3aWxsIGZpbHRlciBvdXQgdGhlIGRhdGEgYWJvdXQgdG90YWxzIGFuZCBkaWZmZXJlbnQgcmFjaWFsL2V0aG5pYyBncm91cHMgZm9yIG5vdy4gV2Ugd2lsbCBhbHNvIHVzZSB0aGUgYGZhY2V0X3dyYXAoKWAgZnVuY3Rpb24gdG8gbWFrZSBzdWJwbG90cyBiYXNlZCBvbiB0aGUgZGVtb2dyYXBoaWMgY2F0ZWdvcmllcywgd2hpY2ggd2UgcHV0IGluIGEgdmFyaWFibGUgY2FsbGVkIGBzdWJncm91cHNgIGVhcmxpZXIgd2hlbiB3ZSB3cmFuZ2xlZCB0aGUgZGF0YS4KCmBgYHtyfQpNREVfYWdlX3NleCA8LXBlcmNlbnRzICU+JQogIGZpbHRlcihkYXRhX3R5cGUgPT0gIk1ham9yX0RlcHJlc3NpdmVfRXBpc29kZSIpJT4lCiAgZmlsdGVyKHN1Ymdyb3VwICE9ICJSYWNlL0V0aG5pY2l0eSIpICU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyAhPSAiVE9UQUwiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCAKICAgICAgICAgICAgIHkgPSBQZXJjZW50LCAKICAgICAgICAgZ3JvdXAgPSBEZW1vZ3JhcGhpYywgCiAgICAgICAgIGNvbG9yID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IERlbW9ncmFwaGljKSwgc2l6ZSA9MSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA0LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljcywgUGVyY2VudGFnZXMsIDIwMDQtMjAxOCIpICsKICBmYWNldF93cmFwKH5zdWJncm91cCkrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpIAoKTURFX2FnZV9zZXgKYGBgCgpOaWNlISBOb3cgaXQgaXMgbXVjaCBlYXNpZXIgdG8gdGVsbCBob3cgZWFjaCBncm91cCBoYXMgY2hhbmdlZCBvdmVyIHRpbWUuCgpXZSBjYW4gYWxzbyBhZGQgbGFiZWxzIGRpcmVjdGx5IHRvIHRoZSBsaW5lcyB1c2luZyB0aGUgYGRpcmVjdGxhYmVsc2AgcGFja2FnZS4gVGhlcmUgYXJlIHNldmVyYWwgbWV0aG9kcyB0byBkbyBzby4gU2VlIFtoZXJlXShodHRwOi8vZGlyZWN0bGFiZWxzLnItZm9yZ2Uuci1wcm9qZWN0Lm9yZy9kb2NzL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgdGhlIG9wdGlvbnMgZm9yIGFkZGluZyBsYWJlbHMgd2l0aCB0aGlzIHBhY2thZ2UuICBXZSB3aWxsIHVzZSB0aGUgYCJmYXIuZnJvbS5vdGhlcnMuYm9yZGVycyJgIG1ldGhvZCBzbyB0aGF0IG91ciBsYWJlbHMgZG9uJ3Qgb3ZlcmxhcCBvbmUgYW5vdGhlci4gV2Ugd2lsbCBhbHNvIHVzZSBgZGwudHJhbnMoKWAgb2YgdGhlIGBkaXJlY3RsYWJlbHNgIHBhY2thZ2UgdG8gbW92ZSB0aGUgbGFiZWxzIHNsaWdodGx5IHVwd2FyZCAoYHkgPSB5ICswLjM1YCkgYW5kIHRvIHRoZSBsZWZ0IChgeCA9IHggLTAuMWApLiBXZSB3aWxsIHVzZSB0aGUgYGRsLm1vdmUoKWAgZnVuY3Rpb24gb2YgdGhlIGBkaXJlY3RsYWJlbHNgIHBhY2thZ2UgdG8gbW92ZSBvbmUgb2YgdGhlIGxhYmVscyB0byBhIHBhcnRpY3VsYXIgbG9jYXRpb24uIAoKCmBgYHtyfQpkaXJlY3RsYWJlbHM6OmRpcmVjdC5sYWJlbChNREVfYWdlX3NleCwgbGlzdCgKICBkbC50cmFucyh5ID0geSArMC4zOCwgeCA9IHggLTAuMSksIAogICJmYXIuZnJvbS5vdGhlcnMuYm9yZGVycyIsCiAgY2V4ID0gLjgsIAogIGRsLm1vdmUoIkFnZV8xNC0xNSIsIHggPSAyMDA4LCB5ID0xMCkpKQoKYGBgCgpUaGlzIGxvb2tzIHZlcnkgY2xlYXIgbm93IQoKV2UgY2FuIHNlZSB0aGF0IHRoZSBtYWpvcml0eSBvZiBpbmRpdmlkdWFscyB0aGF0IHJlcG9ydGVkIGV4cGVyaWVuY2luZyBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSBpbiB0aGUgcGFzdCB5ZWFyIHdlcmUgaW4gYW4gb2xkZXIgYWdlIGJyYWNrZXQuIFdlIGNhbiBhbHNvIHNlZSB0aGF0IHRoZSB0cmVuZCBoYXMgYmVlbiBpbmNyZWFzaW5nIGZvciBhbGwgdGhyZWUgYWdlIGJyYWNrZXRzIHNpbmNlIHJvdWdobHkgMjAxMS4KCldlIGNhbiBhbHNvIHNlZSBhbiBpbmNyZWFzZSBmb3IgYm90aCBzZXhlcyBzaW5jZSBhYm91dCAyMDExLCBidXQgdGhlcmUgaXMgYSBzdGVlcGVyIGluY3JlYXNlIGZvciBmZW1hbGVzLiBGdXJ0aGVybW9yZSBGZW1hbGVzIGhhdmUgYSBtdWNoIGhpZ2hlciByYXRlIHRoYW4gbWFsZXMgZm9yIGFsbCB5ZWFycy4KCkxldCdzIG1ha2UgdGhlIHNhbWUgcGxvdCB3aXRoIGEgZGlmZmVyZW50IHNoYWRlZCBiYWNrZ3JvdW5kIGZvciB0aGUgeWVhcnMgb2YgdGhlIGluY3JlYXNlIGxpa2Ugd2UgZGlkIGZvciB0aGUgdG90YWwgcGxvdC4KCmBgYHtyfQpNREVfYWdlX3NleCA8LXBlcmNlbnRzICU+JQogIGZpbHRlcihkYXRhX3R5cGUgPT0gIk1ham9yX0RlcHJlc3NpdmVfRXBpc29kZSIpJT4lCiAgZmlsdGVyKHN1Ymdyb3VwICE9ICJSYWNlL0V0aG5pY2l0eSIpICU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyAhPSAiVE9UQUwiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCB5ID0gUGVyY2VudCwgZ3JvdXAgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX3JlY3QoeG1pbiA9IDIwMTEsIHhtYXggPSBJbmYsICAKICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsICAKICAgICAgICAgICAgZmlsbCA9ICJsaWdodCBncmF5IikrCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IERlbW9ncmFwaGljKSwgc2l6ZSA9MSkgKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA0LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljcywgUGVyY2VudGFnZXMsIDIwMDQtMjAxOCIpICsKICBmYWNldF93cmFwKH5zdWJncm91cCkrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpIAoKTURFX2FnZV9zZXggPC1kaXJlY3QubGFiZWwoTURFX2FnZV9zZXgsIGxpc3QoCiAgZGwudHJhbnMoeSA9IHkgKzAuMzgsIHggPSB4IC0wLjIpLCAKICAiZmFyLmZyb20ub3RoZXJzLmJvcmRlcnMiLCAKICBjZXggPSAuOCwgCiAgZGwubW92ZSgiQWdlXzE0LTE1IiwgeCA9IDIwMDgsIHkgPTEwKSkpCk1ERV9hZ2Vfc2V4CmBgYAoKU28gd2hhdCBtaWdodCBiZSBhY2NvdW50aW5nIGZvciB0aGlzPwoKClRoaXMgY3Jvc3MtY3VsdHVyYWwgW3JldmlldyBhcnRpY2xlXShodHRwczovL3d3dy5uY2JpLm5sbS5uaWguZ292L3BtYy9hcnRpY2xlcy9QTUMzMzMwMTYxLyl7dGFyZ2V0PSJfYmxhbmsifSBwdWJsaXNoZWQgaW4gMjAxMiBzdWdnZXN0cyB0aGF0IGFzcGVjdHMgcmVsYXRlZCB0byBsaWZlLXN0eWxlIGR1ZSB0byBtb2Rlcm5pdHkgbWF5IGJlIGNhdXNpbmcgaW5jcmVhc2VkIGRlcHJlc3Npb24gcmF0ZXM6IAoKPiBNb2Rlcm4gcG9wdWxhdGlvbnMgYXJlIGluY3JlYXNpbmdseSBvdmVyZmVkLCBtYWxub3VyaXNoZWQsIHNlZGVudGFyeSwgc3VubGlnaHQtZGVmaWNpZW50LCBzbGVlcC1kZXByaXZlZCwgYW5kIHNvY2lhbGx5LWlzb2xhdGVkLiBUaGVzZSBjaGFuZ2VzIGluIGxpZmVzdHlsZSBlYWNoIGNvbnRyaWJ1dGUgdG8gcG9vciBwaHlzaWNhbCBoZWFsdGggYW5kIGFmZmVjdCB0aGUgaW5jaWRlbmNlIGFuZCB0cmVhdG1lbnQgb2YgZGVwcmVzc2lvbi4KCkFuZCBhbHRob3VnaCB0aGlzIG1heSBiZSB0cnVlIGdsb2JhbGx5LCB0aGUgVVMgaGFzIGJlZW4gYXJndWFibHkgZXhwZXJpZW5jaW5nIHRoZXNlIG1vZGVybiBsaWZlc3R5bGUgY2hhbmdlcyBmb3IgeWVhcnMgcHJpb3IgdG8gdGhpcyBzdGVlcCBpbmNyZWFzZSBpbiAyMDExLgoKU28gd2hhdCBtaWdodCBoYXZlIGhhcHBlbmVkIGluIHRoZSBVUyBhcm91bmQgdGhpcyB0aW1lPwoKVGhlcmUgaXMgbGFyZ2UgYW1vdW50IG9mIGxpdGVyYXR1cmUgYWJvdXQgaG93IHRoZSB1c2Ugb2Ygc21hcnQgcGhvbmUgYW5kIHNvY2lhbCBtZWRpYSBtYXkgaGF2ZSBsZWFkIHRvIGluY3JlYXNlZCBkZXByZXNzaW9uIHJhdGVzLiBTZWUgdGhpcyBbYXJ0aWNsZV0oaHR0cHM6Ly9jaGlsZG1pbmQub3JnL2FydGljbGUvaXMtc29jaWFsLW1lZGlhLXVzZS1jYXVzaW5nLWRlcHJlc3Npb24vKXt0YXJnZXQ9Il9ibGFuayJ9IHdoaWNoIGxpbmtzIHRvIG1hbnkgc2NpZW50aWZpYyBhcnRpY2xlcyBvbiB0aGUgc3ViamVjdC4gCgpUaGlzIGhhcyBiZWVuIGEgY29udHJvdmVyc2lhbCB0b3BpYyBkdWUgdG8gY29uZmxpY3RpbmcgZmluZGluZ3MsIGxpa2VseSBkdWUgdG8gZm9jdXMgb24gZGlmZmVyZW50IHNpdGVzIGFuZCBhc3BlY3RzIG9mIHNvY2lhbCBtZWRpYSBhY3Jvc3MgZGlmZmVyZW50IHN0dWRpZXMuIAoKVGhlIGFydGljbGUgcG9pbnRzIG91dCB0aGF0IHRoZSB0cnVlIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHNvY2lhbCBtZWRpYSB1c2UgYW5kIGRlcHJlc3Npb24gbWF5IGJlIG51YW5jZWQuIFNvbWUgaW5kaXZpZHVhbHMgd2hvIGhhdmUgaGlnaCBmYWNlLXRvLWZhY2UgbGV2ZWxzIG9mIGludGVyYWN0aW9uIG9yIGxhY2sgb2YgdGhlIG9wcG9ydHVuaXR5IHRvIGludGVyYWN0IHdpdGggb3RoZXJzIGZhY2UtdG8tZmFjZSAoZHVlIHRvIHZhcmlvdXMgYmFycmllcnMgbGlrZSBnZW9ncmFwaHkpLCBtYXkgYWN0dWFsbHkgZXhwZXJpZW5jZSBsb3dlciByaXNrIGZvciBkZXByZXNzaW9uIHdpdGggbW9yZSBzb2NpYWwgbWVkaWEgdXNlLiAKCkZ1cnRoZXJtb3JlLCBkaWZmZXJlbnQgc29jaWFsIG1lZGlhIHBsYXRmb3JtcyBtYXkgdmFyeSBmb3IgdGhlaXIgaW5mbHVlbmNlIG9uIGRlcHJlc3Npb24uCgpJbnN0YWdyYW0gd2FzIHJlbGVhc2VkIGluIDIwMTAgKHdoaWNoIGlzIGFyb3VuZCB3aGVuIG91ciBwbG90IHN0YXJ0cyB0byBzaG93IHRoZSB1cHdhcmQgaW5jcmVhc2UgaW4gbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlcywgcGFydGljdWxhcmx5IGluIGZlbWFsZXMpIGFuZCBhY2NvcmRpbmcgdG8gdGhlIGFydGljbGU6Cgo+IEltYWdlLWRyaXZlbiBJbnN0YWdyYW0gc2hvd3MgdXAgaW4gc3VydmV5cyBhcyB0aGUgcGxhdGZvcm0gdGhhdCBtb3N0IGxlYWRzIHlvdW5nIHBlb3BsZSB0byByZXBvcnQgZmVlbGluZyBhbnhpZXR5LCBkZXByZXNzaW9uIGFuZCB3b3JyaWVzIGFib3V0IGJvZHkgaW1hZ2UuCgpGdXJ0aGVybW9yZSwgaXQgbWF5IGJlIHNlY29uZGFyeSBlZmZlY3RzIG9mIHNvY2lhbCBtZWRpYSB1c2UsIGxpa2UgbGVzcyBwaHlzaWNhbCBhY3Rpdml0eSBvciBsZXNzIHNsZWVwIHRoYXQgbWF5IGluY3JlYXNlIHRoZSByaXNrIGZvciBkZXByZXNzaW9uLiAKCk5vdyBsZXQncyB0YWtlIGEgbG9vayBhdCBob3cgdGhlIHJhdGUgb2YgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlcyBoYXMgY2hhbmdlZCBhY3Jvc3MgdGltZSBmb3IgZGlmZmVyZW50IHJhY2lhbC9ldGhuaWMgZ3JvdXBzLgoKU2luY2Ugd2UgaGF2ZSBzbyBtYW55IGdyb3Vwcywgd2UgcHJvYmFibHkgZG9uJ3Qgd2FudCB0byBkaXJlY3RseSBsYWJlbCB0aGUgbGluZXMgdGhpcyB0aW1lLiBJbnN0ZWFkLCB3ZSB3aWxsIHJlbHkgb24gdGhlIGxlZ2VuZCB0aGF0IHdpbGwgYmUgYXV0b21hdGljYWxseSBjcmVhdGVkLgoKV2Ugd2lsbCB1c2UgdGhlIHRoZSBgZmN0X3Jlb3JkZXJgIGZ1bmN0aW9uIG9mIHRoZSBgZm9yY2F0c2AgcGFja2FnZSB0byBvcmRlciB0aGUgcmFjaWFsL2V0aG5pYyBncm91cHMgaW4gdGhlIGxlZ2VuZCBiYXNlZCBvbiB0aGUgbGFzdCB2YWx1ZSAodXNpbmcgYHRhaWwoKWApIG9mIHRoZSBgUGVyY2VudGAgdmFyaWFibGUuCgpXZSB3aWxsIGFsc28gbWFudWFsbHkgY29sb3Igb3VyIGxpbmVzIGJhc2VkIG9uIGEgY29sb3IgcGFsZXR0ZSBjYWxsZWQgW3ZpcmlkaXNdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy92aXJpZGlzL3ZpZ25ldHRlcy9pbnRyby10by12aXJpZGlzLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0sIHdoaWNoIGlzIG1vcmUgZGlzY2VybmlibGUgZm9yIGluZGl2aWR1YWxzIHdpdGggY29sb3ItYmxpbmRuZXNzLiBUbyBkbyBzbyB3ZSB3aWxsIHVzZSB0aGUgYHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpYCBmdW5jdGlvbiBvZiB0aGUgYGdncGxvdDJgIHBhY2thZ2UsIHdoaWNoIGlzIGludGVuZGVkIGZvciBjb2xvcmluZyBkaXNjcmV0ZSB2YWx1ZXMuCgpgYGB7cn0KCk1ERV9yYWNlIDwtcGVyY2VudHMgJT4lCiAgZmlsdGVyKGRhdGFfdHlwZSA9PSAiTWFqb3JfRGVwcmVzc2l2ZV9FcGlzb2RlIiklPiUKICBmaWx0ZXIoc3ViZ3JvdXAgPT0gIlJhY2UvRXRobmljaXR5IikgJT4lCiAgICAgbXV0YXRlKERlbW9ncmFwaGljID0gZmN0X3Jlb3JkZXIoRGVtb2dyYXBoaWMsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFBlcmNlbnQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhaWwsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSAxLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZGVzYyA9IFRSVUUpKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IFllYXIsIAogICAgICAgICAgICAgICB5ID0gUGVyY2VudCwKICAgICAgICAgICBncm91cCA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fcmVjdCh4bWluID0gMjAxMSwgeG1heCA9IEluZiwgICAKICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsICAgCiAgICAgICAgICAgIGZpbGwgPSAibGlnaHQgZ3JheSIpKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBEZW1vZ3JhcGhpYyksIHNpemUgPTEpKwogIGZhY2V0X3dyYXAofnN1Ymdyb3VwKSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwNCwgMjAxOCkpICsKICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKSsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3MsIFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgiKSArCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCkpIAoKTURFX3JhY2UKCmBgYAoKVW5mb3J0dW5hdGVseSwgdGhlcmUgaXMgb25seSBvbmUgdmFsdWUgZm9yIGBOSE9QSWAgZ3JvdXAsIHRodXMgc2luY2UgdGhpcyBpcyBhIGxpbmUgcGxvdCwgd2UgZG8gbm90IGhhdmUgZW5vdWdoIHBvaW50cygyIGF0IG1pbmltdW0pIHRvIGNyZWF0ZSBhIGxpbmUsIHNvIGxldHMgcmVtb3ZlIHRoaXMgZ3JvdXAgZnJvbSB0aGUgcGxvdCB0byByZW1vdmUgdGhlIGdyb3VwIGZyb20gdGhlIGxlZ2VuZC4KCmBgYHtyfQpwZXJjZW50cyAlPiUKICBmaWx0ZXIoZGF0YV90eXBlID09ICJNYWpvcl9EZXByZXNzaXZlX0VwaXNvZGUiKSU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyA9PSJOSE9QSSIpCgpNREVfcmFjZSA8LSAgcGVyY2VudHMgJT4lCiAgZmlsdGVyKGRhdGFfdHlwZSA9PSAiTWFqb3JfRGVwcmVzc2l2ZV9FcGlzb2RlIiklPiUKICBmaWx0ZXIoc3ViZ3JvdXAgPT0gIlJhY2UvRXRobmljaXR5IikgJT4lCiAgICBmaWx0ZXIoRGVtb2dyYXBoaWMgIT0gIk5IT1BJIikgJT4lCiAgICAgbXV0YXRlKERlbW9ncmFwaGljID0gZmN0X3Jlb3JkZXIoRGVtb2dyYXBoaWMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGVyY2VudCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFpbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbiA9IDEsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC5kZXNjID0gVFJVRSkpICU+JQogICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCAKICAgICAgICAgICAgICB5ID0gUGVyY2VudCwgCiAgICAgICAgICBncm91cCA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fcmVjdCh4bWluID0gMjAxMSwgeG1heCA9IEluZiwgIAogICAgICAgICAgICB5bWluID0gLUluZiwgeW1heCA9IEluZiwgICAKICAgICAgICAgICAgZmlsbCA9ICJsaWdodCBncmF5IikrCiAgZ2VvbV9saW5lKGFlcyhjb2xvciA9IERlbW9ncmFwaGljKSwgc2l6ZSA9MSkrCiAgZmFjZXRfd3JhcCh+c3ViZ3JvdXApKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA0LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljcywgUGVyY2VudGFnZXMsIDIwMDQtMjAxOCIpICsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgKwogIHNjYWxlX2NvbG9yX3ZpcmlkaXNfZCgpCgpNREVfcmFjZQoKYGBgCgoKQ2Vuc3VzIEJ1cmVhdSBkZWZpbml0aW9uczogIAoxKSAqKkFJQU4qKiBzdGFuZHMgZm9yIEFtZXJpY2FuIEluZGlhbiBhbmQgQWxhc2thIE5hdGl2ZSAgCjIpICoqTkhPUEkqKiBzdGFuZHMgZm9yIE5hdGl2ZSBIYXdhaWlhbiBvciBPdGhlciBQYWNpZmljIElzbGFuZGVyICAKCldlIGNhbiBzZWUgdGhhdCB0aGUgZ3JvdXAgb2YgaW5kaXZpZHVhbHMgd2hvIHJlcG9ydGVkIGFzIGJlaW5nIHR3byBvciBtb3JlIHJhY2VzLCBoYWQgdGhlIGhpZ2hlc3QgcGVyY2VudGFnZXMgb2YgaGF2aW5nIGEgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIGluIHRoZSBwYXN0IHllYXIuIFRob3NlIGdyb3VwIHdobyByZXBvcnRlZCBhcyBCbGFjayBvciBBZnJpY2FuIEFtZXJpY2FuIGhhZCB0aGUgbG93ZXN0IHBlcmNlbnRhZ2VzLiBIb3dldmVyLCB3ZSBjYW4gc2VlIHRoYXQgbW9zdCBvZiB0aGUgcmFjaWFsL2V0aG5pYyBncm91cHMgYXJlIGZhaXJseSBzaW1pbGFyIGFuZCB3ZSBzZWUgYW4gaW5jcmVhc2luZyBmb3IgbW9zdCBncm91cHMgc2luY2UgYXJvdW5kIDIwMTEuIEtlZXAgaW4gbWluZCB0aGUgbGltaXRhdGlvbnMgbGlzdGVkIGluIHRoZSBbKipMaW1pdGF0aW9ucyoqXSBzZWN0aW9uIGFzIHlvdSB2aWV3IHRoZXNlIGZpbmRpbmdzLiBJdCBpcyBwb3NzaWJsZSB0aGF0IHRoaXMgZ3JvdXAgbWF5IGJlIGxlc3MgbGlrZWx5IHRvIHJlcG9ydCBleHBlcmllbmNpbmcgc3ltcHRvbXMgb2YgZGVwcmVzc2lvbi4KCiMjIyBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgd2l0aCBTZXZlcmUgSW1wYWlybWVudAoKTm93IGxldCdzIHRha2UgYSBsb29rIGF0IGhvdyB0aGUgcmF0ZSBvZiB5b3V0aHMgcmVwb3J0aW5nIGhhdmluZyBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSB3aXRoIHNldmVyZSBpbXBhaXJtZW50IGhhcyBjaGFuZ2VkIG92ZXIgdGltZS4gU2VlIHRoZSBbKipXaGF0IGFyZSB0aGUgZGF0YT8qKl0gc2VjdGlvbiBhYm91dCBob3cgc2V2ZXJlIGltcGFpcm1lbnQgd2FzIGRlZmluZWQuIAoKYGBge3J9Ck1ERVMgPC1wZXJjZW50cyAlPiUKICBmaWx0ZXIoZGF0YV90eXBlID09ICJTZXZlcmVfTWFqb3JfRGVwcmVzc2l2ZV9FcGlzb2RlIiklPiUKICBmaWx0ZXIoc3ViZ3JvdXAgIT0gIlJhY2UvRXRobmljaXR5IikgJT4lCiAgZmlsdGVyKERlbW9ncmFwaGljICE9ICJUT1RBTCIpICU+JQogICAgZ2dwbG90KGFlcyh4ID0gWWVhciwgCiAgICAgICAgICAgICAgIHkgPSBQZXJjZW50LAogICAgICAgICAgIGdyb3VwID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9yZWN0KHhtaW4gPSAyMDExLCB4bWF4ID0gSW5mLCAgCiAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCAgCiAgICAgICAgICAgIGZpbGwgPSAibGlnaHQgZ3JheSIpKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBEZW1vZ3JhcGhpYyksIHNpemUgPTEpKwogIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoMjAwNiwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxhYmVscyA9IHNlcSgyMDA2LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGltaXRzID0gYygyMDA2LCAyMDE4KSkgKwogIGxhYnModGl0bGUgPSAiTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIHdpdGggU2V2ZXJlIEltcGFpcm1lbnQgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzLCBQZXJjZW50YWdlcywgMjAwNC0yMDE4IikgKwogIGZhY2V0X3dyYXAofnN1Ymdyb3VwKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBmYWNlID0gImJvbGQiKSwKICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgCgpkaXJlY3QubGFiZWwoTURFUywgbGlzdCgKICBkbC50cmFucyh5ID0geSArMC4zOSwgeCA9IHggLTAuMSksIAogICJmYXIuZnJvbS5vdGhlcnMuYm9yZGVycyIsCiAgY2V4ID0gLjgsIAogIGRsLm1vdmUoIkFnZV8xNC0xNSIsIHg9IDIwMTYuNSwgeSA9IDExKSkpCgoKYGBgCgoKV2UgY2FuIHNlZSB0aGF0IHRoZSBtYWpvcml0eSBvZiBpbmRpdmlkdWFscyB0aGF0IHJlcG9ydGVkIGV4cGVyaWVuY2luZyBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSB3aXRoIHNldmVyZSBpbXBhaXJtZW50IHdlcmUgaW4gYW4gb2xkZXIgYWdlIGJyYWNrZXQsIGhvd2V2ZXIgdGhlcmUgYXBwZWFycyB0byBiZSBhIG1vcmUgZHJhbWF0aWMgY2hhbmdlIGluIHRoZSBtaWRkbGUgYWdlIGdyb3VwIGZyb20gMjAxMS0yMDEyLiBXZSBjYW4gc2VlIGEgdmVyeSBzdGVlcCBpbmNyZWFzZSBpbiB0aGUgZGF0YSBmb3IgdGhlIGZlbWFsZXMgYWZ0ZXIgMjAxMSwgYWdhaW4gdGhpcyBpcyBtdWNoIG1vcmUgc3RlZXAgdGhhbiB0aGUgaW5jcmVhc2Ugc2VlbiBmb3IgbWFsZXMgb3ZlciB0aW1lLgoKTm93IGxldCdzIGxvb2sgYXQgcmFjaWFsL2V0aG5pYyBncm91cHMuCgpgYGB7cn0KUmFjZV9NREVTIDwtICBwZXJjZW50cyAlPiUKICBmaWx0ZXIoZGF0YV90eXBlID09ICJTZXZlcmVfTWFqb3JfRGVwcmVzc2l2ZV9FcGlzb2RlIiklPiUKICBmaWx0ZXIoc3ViZ3JvdXAgPT0gIlJhY2UvRXRobmljaXR5IikgJT4lCiAgICBtdXRhdGUoRGVtb2dyYXBoaWMgPSBmY3RfcmVvcmRlcihEZW1vZ3JhcGhpYywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBQZXJjZW50LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhaWwsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuZGVzYyA9IFRSVUUpKSAlPiUKICAgIGdncGxvdChhZXMoeCA9IFllYXIsCiAgICAgICAgICAgICAgIHkgPSBQZXJjZW50LAogICAgICAgICAgIGdyb3VwID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9yZWN0KHhtaW4gPSAyMDExLCB4bWF4ID0gSW5mLCAgCiAgICAgICAgICAgIHltaW4gPSAtSW5mLCB5bWF4ID0gSW5mLCAgCiAgICAgICAgICAgIGZpbGwgPSAibGlnaHQgZ3JheSIpKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBEZW1vZ3JhcGhpYyksIHNpemUgPTEpKwogIGZhY2V0X3dyYXAofnN1Ymdyb3VwKSsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDYsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwNiwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwNiwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSB3aXRoIFNldmVyZSBJbXBhaXJtZW50IGluIFBhc3QgWWVhclxuYW1vbmcgUGVyc29ucyBBZ2VkIDEyIHRvIDE3IiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDYtMjAxOCIpKwogIHRoZW1lX2xpbmVkcmF3KCkrCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSArCiAgc2NhbGVfY29sb3JfdmlyaWRpc19kKCkKCgpSYWNlX01ERVMKCmBgYAoKQ2Vuc3VzIEJ1cmVhdSBkZWZpbml0aW9uczogIAoxKSAqKkFJQU4qKiBzdGFuZHMgZm9yIEFtZXJpY2FuIEluZGlhbiBhbmQgQWxhc2thIE5hdGl2ZSAgCjIpICoqTkhPUEkqKiBzdGFuZHMgZm9yIE5hdGl2ZSBIYXdhaWlhbiBvciBPdGhlciBQYWNpZmljIElzbGFuZGVyIAoKV2Ugc2VlIHNpbWlsYXIgdHJlbmRzIGFzIHdlIHNhdyBmb3IgdGhlIHByZXZpb3VzIHJhY2lhbC9ldGhuaWMgZ3JvdXAgcGxvdC4gVGhlIHJhdGUgaXMgaGlnaGVzdCBmb3IgdGhvc2Ugd2hvIGFyZSB0d28gYXJlIG1vcmUgcmFjZXMgYW5kIGxvd2VzdCBmb3IgdGhvc2Ugd2hvIGFyZSBCbGFjayBvciBBZnJpY2FuIEFtZXJpY2FuLiBUaGUgZGF0YSBmb3IgdGhlIEFJQU4gZ3JvdXAgaXMgc3BhcnNlLCBzbyBpdCBpcyB1bmNsZWFyIGlmIHRoZWlyIGxldmVscyB3b3VsZCBiZSBsb3dlc3Qgb24gdGhlIGxhc3QgeWVhci4KCiMjIyBSZWNlaXB0IG9mIHRyZWF0bWVudCBmb3IgZGVwcmVzc2lvbiBmb3IgeW91dGhzIHdobyBoYWQgYSBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUKCk5vdyB3ZSB3aWxsIHRha2UgYSBsb29rIGF0IHRob3NlIHdobyByZWNlaXZlZCB0cmVhdG1lbnQuIEZpcnN0IGxldCdzIGxvb2sgb3ZlcmFsbC4KCmBgYHtyfQpUcmVhdF90b3RhbCA8LXBlcmNlbnRzICU+JQogIGZpbHRlcihkYXRhX3R5cGUgPT0gInRyZWF0bWVudCIpJT4lCiAgZmlsdGVyKERlbW9ncmFwaGljID09ICJUT1RBTCIpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIAogICAgICAgICAgICAgeSA9IFBlcmNlbnQsIAogICAgICAgICAgICAgZ3JvdXAgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX3JlY3QoeG1pbiA9IDIwMTEsIHhtYXggPSBJbmYsICAKICAgICAgICAgICAgeW1pbiA9IC1JbmYsIHltYXggPSBJbmYsICAgCiAgICAgICAgICAgIGZpbGwgPSAibGlnaHQgZ3JheSIpKwogIGdlb21fbGluZShhZXMoY29sb3IgPSBEZW1vZ3JhcGhpYyksIHNpemUgPSAxLjUpICsKICAjZ2VvbV9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgc2UgPSBGQUxTRSkrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDQsIDIwMTgpKSArCiAgbGFicyh0aXRsZSA9ICJUaGUgUmF0ZSBvZiBZb3V0aHMgQWdlZCAxMiB0byAxNyBSZXBvcnRpbmcgSGF2aW5nIGEgXG4gTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIGluIHRoZSBQYXN0IFllYXIgaXMgSW5jcmVhc2luZyIpKwogIHRoZW1lX2NsYXNzaWMoKSsKICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgICAgICBsZWdlbmQucG9zaXRpb24gPSAibm9uZSIpIAoKVHJlYXRfdG90YWwKCmBgYAoKT3ZlcmFsbCByb3VnaGx5IDQwIHBlcmNlbnQgb2YgeW91dGhzIHdobyBzZWxmLXJlcG9ydGVkIGV4cGVyaWVuY2luZyBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSwgYWxzbyByZWNlaXZlZCB0cmVhdG1lbnQgZm9yIGRlcHJlc3Npb24uIAoKVGhpcyByYXRlIGlzIGluY3JlYXNpbmcgb3ZlcnRpbWUgbGlrZSB0aGUgdHJlbmQgb2YgdGhvc2Ugd2hvIGhhZCBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSwgeWV0IHRoZSBkYXRhIGlzIG11Y2ggbW9yZSB2YXJpYWJsZSBmcm9tIG9uZSB5ZWFyIHRvIHRoZSBuZXh0LiAKCmBgYHtyfQp0cmVhdDwtcGVyY2VudHMgJT4lCiAgZmlsdGVyKGRhdGFfdHlwZSA9PSAidHJlYXRtZW50IiklPiUKICBmaWx0ZXIoc3ViZ3JvdXAgIT0gIlJhY2UvRXRobmljaXR5IiklPiUKICBmaWx0ZXIoc3ViZ3JvdXAgIT0gIlRvdGFsIiklPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCAKICAgICAgICAgICAgIHkgPSBQZXJjZW50LCAKICAgICAgICAgICAgIGdyb3VwID0gRGVtb2dyYXBoaWMsIAogICAgICAgICAgICAgY29sb3IgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX2xpbmUoIHNpemUgPTEpICsKICBmYWNldF93cmFwKH5zdWJncm91cCkrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDQsIDIwMTgpKSArIAogIGxhYnModGl0bGUgPSAiUmVjZWlwdCBvZiBUcmVhdG1lbnQgZm9yIERlcHJlc3Npb24gaW4gUGFzdCBZZWFyIGFtb25nXG5QZXJzb25zIEFnZWQgMTIgdG8gMTcgd2l0aCBNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyIiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDQtMjAxOCIpKwogIHRoZW1lX2xpbmVkcmF3KCkrCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSAKCnRyZWF0PC1kaXJlY3QubGFiZWwodHJlYXQsIGxpc3QoCiAgZGwudHJhbnMoeSA9IHkgLTEuNSwgeCA9IHggLTAuNCksCiAgImZhci5mcm9tLm90aGVycy5ib3JkZXJzIiwgCiAgY2V4ID0gLjgsIAogIGRsLm1vdmUoIkFnZV8xNi0xNyIsIHggPSAyMDEwLCB5ID0gNDIpLAogIGRsLm1vdmUoIkFnZV8xNC0xNSIsIHggPSAyMDE1LCB5ID0gMzgpKSkKCnRyZWF0CmBgYAoKVGhlcmUgc2VlbXMgdG8gYmUgYW4gdXB3YXJkIHRyZW5kLCBidXQgaXQgaXNuJ3QgbmVhcmx5IGFzIG11Y2ggYXMgdGhlIHRyZW5kIHdlIHNhdyBmb3IgdGhlIGluY3JlYXNlIG9mIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZXMuIEluIGdlbmVyYWwsIHRoZSBkYXRhIHNlZW1zIHRvIHZhcnkgbXVjaCBtb3JlIGFzIHdlbGwuCgoKYGBge3J9ClJhY2VfdHJlYXQgPC1wZXJjZW50cyAlPiUKICBmaWx0ZXIoZGF0YV90eXBlID09ICJ0cmVhdG1lbnQiKSU+JQogIGZpbHRlcihzdWJncm91cCA9PSAiUmFjZS9FdGhuaWNpdHkiKSAlPiUKICBtdXRhdGUoRGVtb2dyYXBoaWMgPSBmY3RfcmVvcmRlcihEZW1vZ3JhcGhpYywgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUGVyY2VudCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGFpbCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuID0gMSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLmRlc2MgPSBUUlVFKSkgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwKICAgICAgICAgICAgIHkgPSBQZXJjZW50LCAKICAgICAgICAgZ3JvdXAgPSBEZW1vZ3JhcGhpYywgCiAgICAgICAgIGNvbG9yID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9saW5lKHNpemUgPTEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwOSwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIlJlY2VpcHQgb2YgVHJlYXRtZW50IGZvciBEZXByZXNzaW9uIGluIFBhc3QgWWVhciBhbW9uZ1xuUGVyc29ucyBBZ2VkIDEyIHRvIDE3IHdpdGggTWFqb3IgRGVwcmVzc2l2ZSBFcGlzb2RlIiwKICAgICAgIHN1YnRpdGxlID0gIkJ5IERlbW9ncmFwaGljIENoYXJhY3RlcmlzdGljczogUGVyY2VudGFnZXMsIDIwMDQtMjAxOCIpKwogIHRoZW1lX2xpbmVkcmF3KCkrCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSArCiAgICBzY2FsZV9jb2xvcl92aXJpZGlzX2QoKQoKUmFjZV90cmVhdAoKYGBgCkl0IGxvb2tzIGFzIHRob3VnaCB5b3V0aHMgd2hvIHJlcG9ydCBhcyBiZWluZyB3aGl0ZSByZWNlaXZlZCB0aGUgbW9zdCBjYXJlIGZyb20gbWVudGFsIGhlYWx0aCBzZXJ2aWNlcy4KCgojIyMgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcwoKV2Ugd2lsbCBhbHNvIHRha2UgYSBsb29rIGF0IHdoZXJlIHlvdXRocyBhcmUgcmVjZWl2aW5nIHRyZWF0bWVudCBieSB1c2luZyB2YWx1ZXMgZnJvbSB0YWJsZTExLjFiIHdoaWNoIGhhcyB0aGUgcGVyY2VudGFnZSB2YWx1ZXMgZm9yIGNvdW50cyBwcmVzZW50ZWQgaW4gdGFibGUxMS4xYS4KCgpXZSBjYW4gdXNlIHRoZSBgc3RyX2RldGVjdCgpYCBmdW5jdGlvbiBvZiB0aGUgYHN0cmluZ3JgIHBhY2thZ2UgdG8gZmlsdGVyIGZvciB0aGUgdmFsdWVzIG9mIHRoZSBgc2hvcnRfbGFiZWxgIHZhcmlhYmxlIHRoYXQgaGFzIHRoZSB3b3JkIGB0b3RhbGAgaW4gaXQuIAoKYGBge3J9CnBsb3RNSFMgPC10YWJsZTExLjFiICU+JQogIGZpbHRlcihzdHJpbmdyOjpzdHJfZGV0ZWN0KHNob3J0X2xhYmVsLCAidG90YWwiKSApICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIAogICAgICAgICAgICAgeSA9IFBlcmNlbnQsIAogICAgICAgICBncm91cCA9IE1IU19zZXR0aW5nLCAKICAgICAgICAgY29sb3IgPSBzaG9ydF9sYWJlbCkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDEpICsKICBmYWNldF93cmFwKH50eXBlKSsKICBnZ3Bsb3QyOjpzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDksIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwOSwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwOSwgMjAxOCkpICsKICBnZ3Bsb3QyOjpsYWJzKHRpdGxlID0gIlNldHRpbmdzIFdoZXJlIE1lbnRhbCBIZWFsdGggU2VydmljZXMgV2VyZSBSZWNlaXZlZCBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJQZXJjZW50YWdlcywgMjAwMi0yMDE4IikrCiAgdGhlbWVfbGluZWRyYXcoKSsKICB0aGVtZShzdHJpcC50ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgZmFjZSA9ICJib2xkIiksCiAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTApKSAKCnBsb3RNSFMgPC1kaXJlY3QubGFiZWwocGxvdE1IUywgbGlzdCgKICBkbC50cmFucyh5ID0geSArMC4zNSwgeCA9IHggLTAuMSksCiAgImZhci5mcm9tLm90aGVycy5ib3JkZXJzIiwgCiAgY2V4ID0gLjgsIAogIGRsLm1vdmUoIk91dHBhdGllbnQgdG90YWwiLCB4ID0gMjAxNSwgeSA9MTEpKSkKCnBsb3RNSFMKYGBgCgpXZSBjYW4gc2VlIHRoYXQgeW91dGhzIGFwcGVhciB0byBiZSByZWNlaXZpbmcgY2FyZSBpbiBub25zcGVjaWFsdHkgZmFjaWxpdGllcyBhdCBhIHNsaWdodGx5IGhpZ2hlciByYXRlIHRoYW4gdGhhdCBvZiBzcGVjaWFsdHkgZmFjaWxpdGllcy4gSG93ZXZlciwgdGhlIHJhdGVzIGFwcGVhciB0byBiZSB2ZXJ5IHNpbWlsYXIgYW5kIHRoZSByZWxhdGl2ZSBkaWZmZXJlbmNlcyBhcHBlYXIgdG8gYmUgY29uc2lzdGVudCBhY3Jvc3MgdGltZS4KCkxldCdzIHRha2UgYSBsb29rIGF0IHN1YmNhdGVnb3JpZXMgb2YgbWVudGFsIGhlYWx0aCBzZXJ2aWNlcy4KU28gbm93IHdlIHdpbGwgZmlsdGVyIGZvciB2YWx1ZXMgd2l0aGluIHRoZSBgc2hvcnRfbGFiZWxgIHZhcmlhYmxlIHRoYXQgZG8gbm90IGNvbnRhaW4gdGhlIHdvcmQgInRvdGFsIiBieSB1c2luZyBhIGAhYCBpbiBmcm9udCBvZiB0aGUgYHN0cl9kZWN0ZWN0YCBzdGF0ZW1lbnQuCgpgYGB7cn0KcGxvdE1IU1MgPC10YWJsZTExLjFiICU+JQogIGZpbHRlcighc3RyX2RldGVjdChzaG9ydF9sYWJlbCwgInRvdGFsIikpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIAogICAgICAgICAgICAgeSA9IFBlcmNlbnQsIAogICAgICAgICBncm91cCA9IE1IU19zZXR0aW5nLCAKICAgICAgICAgY29sb3IgPSBzaG9ydF9sYWJlbCkpICsKICBnZW9tX2xpbmUoc2l6ZSA9IDEpICsKICBmYWNldF93cmFwKH4gdHlwZSkrCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDAyLCAyMDE5LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDIsIDIwMTksIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDIsIDIwMTkpKSArCiAgbGFicyh0aXRsZSA9ICJTZXR0aW5ncyBXaGVyZSBNZW50YWwgSGVhbHRoIFNlcnZpY2VzIFdlcmUgUmVjZWl2ZWQgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiUGVyY2VudGFnZXMsIDIwMDItMjAxOCIpKwogIHRoZW1lX2xpbmVkcmF3KCkrCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSkgCgpwbG90TUhTUyA8LWRpcmVjdC5sYWJlbChwbG90TUhTUywgbGlzdCgKICBkbC50cmFucyh5ID0geSArMC4zKSwKICAiZmFyLmZyb20ub3RoZXJzLmJvcmRlcnMiLCAKICBkbC5tb3ZlKCJTY2hvb2wgVGhlcmFwaXN0IiwgMjAxMCwgMTApLCAKICBkbC5tb3ZlKCJGb3N0ZXJjYXJlIiwgMjAxMCwgMSksIAogIGRsLm1vdmUoIlRoZXJhcGlzdCIsIHg9MjAwOSwgeSA9IDEwLjUpKSkKcGxvdE1IU1MKYGBgCgoKCk9LLCBzbyBub3cgd2Uga25vdyBob3cgdGhlIHJhdGVzIG9mIGRpZmZlcmVudCBzdWJncm91cHMgY29tcGFyZSBmb3IgaGF2aW5nIGEgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIGluIHRoZSBwYXN0IHllYXIsIGhhdmluZyBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSB3aXRoIHNldmVyZSBpbXBhaXJtZW50LCBhbmQgcmVjZWl2aW5nIHRyZWF0bWVudC4gV2UgYWxzbyBrbm93IHdoZXJlIHlvdXRocyBhcmUgdHlwaWNhbGx5IGdldHRpbmcgdHJlYXRtZW50LiBCdXQgaG93IGRvIHRoZSByYXRlcyBvZiBoYXZpbmcgYSBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGUgaW4gdGhlIHBhc3QgeWVhciwgaGF2aW5nIGEgbWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIHdpdGggc2V2ZXJlIGltcGFpcm1lbnQsIGFuZCByZWNlaXZpbmcgdHJlYXRtZW50IGNvbXBhcmUgd2l0aGluIGVhY2ggZ3JvdXA/CgojIyMgT3ZlcmFsbCBvdXRjb21lcyBieSBncm91cAoKYGBge3J9CnNleF9vdXRjb21lcyA8LXBlcmNlbnRzICU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyAlaW4lIGMoIk1hbGUiLCAiRmVtYWxlIiwgIlRPVEFMIikpICU+JQogIGdncGxvdChhZXMoeCA9IFllYXIsIAogICAgICAgICAgICAgeSA9IFBlcmNlbnQsIAogICAgICAgICBjb2xvciA9IERlbW9ncmFwaGljKSkgKwogIGdlb21fbGluZShhZXMobGluZXR5cGU9IGRhdGFfdHlwZSksIHNpemUgPSAxKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGJyZWFrcyA9IHNlcSgyMDA0LCAyMDE4LCBieT0xKSwKICAgICAgICAgICAgICAgICAgICAgbGFiZWxzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsaW1pdHMgPSBjKDIwMDQsIDIwMTgpKSArCiAgbGFicyh0aXRsZSA9ICJNYWpvciBEZXByZXNzaXZlIEVwaXNvZGUgaW4gUGFzdCBZZWFyXG5hbW9uZyBQZXJzb25zIEFnZWQgMTIgdG8gMTciLAogICAgICAgc3VidGl0bGUgPSAiQnkgRGVtb2dyYXBoaWMgQ2hhcmFjdGVyaXN0aWNzLCBQZXJjZW50YWdlcywgMjAwNC0yMDE4IikgKwogIGZhY2V0X3dyYXAofkRlbW9ncmFwaGljLCBzdHJpcC5wb3NpdGlvbiA9ICJ0b3AiKSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBndWlkZXMoY29sb3IgPSBGQUxTRSkKCnNleF9vdXRjb21lcyAKYGBgCgpXZSBjYW4gc2VlIHRoYXQgYSBsYXJnZSBwb3J0aW9uIG9mIGluZGl2aWR1YWxzIGV4cGVyaWVuY2luZyBhIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZSBoYXZlIGFuIGVwaXNvZGUgd2l0aCBzZXZlcmUgaW1wYWlybWVudCBmb3IgZWFjaCBncm91cC4gRmVtYWxlcyBoYXZlIGEgaGlnaGVyIHJhdGUgb2YgYm90aCB0eXBlcyBvZiBlcGlzb2RlIGFuZCBvZiB0cmVhdG1lbnQuIEFsdGhvdWdoIGZlbWFsZXMgaGF2ZSBtb3JlIHRoYW4gZG91YmxlIHRoZSByYXRlIG9mIHJlcG9ydGVkIGVwaXNvZGVzLCB0aGV5IHJlY2VpdmUgYSByZWxhdGl2ZWx5IHNpbWlsYXIgcmF0ZSBvZiB0cmVhdG1lbnQgYXMgbWFsZXMgZm9yIGRlcHJlc3Npb24uIFRoaXMgc3VnZ2VzdHMgdGhhdCBmZW1hbGVzIGFyZSBlaXRoZXIgbW9yZSBsaWtlbHkgdGhhbiBtYWxlcyB0byBzZWxmLXJlcG9ydCBkZXByZXNzaW9uIHN5bXB0b21zIGluIHN1cnZleXMsIG9yIGZlbWFsZXMgbWF5IG5vdCBiZSByZWNlaXZpbmcgYXMgbXVjaCBjYXJlIGRlc3BpdGUgdGhlIGxhcmdlciBuZWVkLiAKCmBgYHtyfQphZ2Vfb3V0Y29tZXMgPC1wZXJjZW50cyAlPiUKICBmaWx0ZXIoc3ViZ3JvdXAgPT0gIkFnZSIpICU+JQogICNmaWx0ZXIoRGVtb2dyYXBoaWMgIT0gIk5IT1BJIikgJT4lCiAgZ2dwbG90KGFlcyh4ID0gWWVhciwgCiAgICAgICAgICAgICB5ID0gUGVyY2VudCwgCiAgICAgICAgIGNvbG9yID0gRGVtb2dyYXBoaWMpKSArCiAgZ2VvbV9saW5lKGFlcyhsaW5ldHlwZT0gZGF0YV90eXBlKSwgc2l6ZSA9IDEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwNCwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3MsIFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgiKSArCiAgZmFjZXRfd3JhcCh+RGVtb2dyYXBoaWMsIHN0cmlwLnBvc2l0aW9uID0gInRvcCIpKwogIHRoZW1lX2xpbmVkcmF3KCkrCiAgdGhlbWUoc3RyaXAudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCwgZmFjZSA9ICJib2xkIiksCiAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDkwKSwKICAgICAgbGVnZW5kLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICBsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikrCiAgZ3VpZGVzKGNvbG9yID0gRkFMU0UpCgphZ2Vfb3V0Y29tZXMgCgpgYGAKQWxsIGFnZSBncm91cHMgc2hvdyBhIHNpbWlsYXIgcmF0aW8gb2Ygc2V2ZXJlIG1ham9yIGRlcHJlc3NpdmUgZXBpc29kZXMgZm9yIHRob3NlIHRoYXQgZXhwZXJpZW5jZWQgYW4gZXBpc29kZS4gCmBgYHtyLCBmaWcuaGVpZ2h0PTEwfQpyYWNlX291dGNvbWVzIDwtcGVyY2VudHMgJT4lCiAgZmlsdGVyKHN1Ymdyb3VwID09ICJSYWNlL0V0aG5pY2l0eSIpICU+JQogIGZpbHRlcihEZW1vZ3JhcGhpYyAhPSAiTkhPUEkiKSAlPiUKICBnZ3Bsb3QoYWVzKHggPSBZZWFyLCAKICAgICAgICAgICAgIHkgPSBQZXJjZW50LCAKICAgICAgICAgY29sb3IgPSBEZW1vZ3JhcGhpYykpICsKICBnZW9tX2xpbmUoYWVzKGxpbmV0eXBlPSBkYXRhX3R5cGUpLCBzaXplPTEpICsKICBzY2FsZV94X2NvbnRpbnVvdXMoYnJlYWtzID0gc2VxKDIwMDQsIDIwMTgsIGJ5PTEpLAogICAgICAgICAgICAgICAgICAgICBsYWJlbHMgPSBzZXEoMjAwNCwgMjAxOCwgYnk9MSksCiAgICAgICAgICAgICAgICAgICAgIGxpbWl0cyA9IGMoMjAwNCwgMjAxOCkpICsKICBsYWJzKHRpdGxlID0gIk1ham9yIERlcHJlc3NpdmUgRXBpc29kZSBpbiBQYXN0IFllYXJcbmFtb25nIFBlcnNvbnMgQWdlZCAxMiB0byAxNyIsCiAgICAgICBzdWJ0aXRsZSA9ICJCeSBEZW1vZ3JhcGhpYyBDaGFyYWN0ZXJpc3RpY3MsIFBlcmNlbnRhZ2VzLCAyMDA0LTIwMTgiKSArCiAgZmFjZXRfd3JhcCh+RGVtb2dyYXBoaWMsIHN0cmlwLnBvc2l0aW9uID0gInRvcCIsIG5yb3cgPSA0KSsKICB0aGVtZV9saW5lZHJhdygpKwogIHRoZW1lKHN0cmlwLnRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgsIGZhY2UgPSAiYm9sZCIpLAogICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA5MCksCiAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpKwogIGd1aWRlcyhjb2xvciA9IEZBTFNFKQpyYWNlX291dGNvbWVzCgpgYGAKCkFsbCByYWNpYWwgYW5kIGV0aG5pYyBncm91cHMgYWxzbyBzaG93IGEgc2ltaWxhciByYXRlIG9mIHNldmVyZSBlcGlzb2RlcyByZWxhdGl2ZSB0byBnZW5lcmFsIGVwaXNvZGUgcmF0ZS4gVGhlIHJhdGUgb2YgcmVjZWl2aW5nIHRyZWF0bWVudCBpcyBmYWlybHkgc2ltaWxhciByZWxhdGl2ZSB0byB0aGUgcGVyY2VudGFnZSBvZiB5b3V0aHMgdGhhdCByZXBvcnRlZCBoYXZpbmcgc3ltcHRvbXMgZm9yIGVhY2ggZ3JvdXAuCgojIyAqKlN1bW1hcnkqKgoqKiogCgojIyMgU3VtbWFyeSBQbG90CgpMZXQncyBtYWtlIGEgcGxvdCB0aGF0IHN1bW1hcml6ZXMgb3VyIG1ham9yIGZpbmRpbmdzLgoKV2Ugd2lsbCB1c2UgdGhlIGBnZ2RyYXcoKWAgZnVuY3Rpb24gb2YgdGhpcyBwYWNrYWdlLiBUaGlzIGFsbG93cyB5b3UgdG8gYWRkIGxhYmVscyBhbmQgb3RoZXIgcGxvdCBhc3BlY3RzIG9uIHRvcCBvZiBleGlzdGluZyBwbG90cy4gVGh1cyBpZiB3ZSB3YW50IHRvIGFkZCBhIHRpdGxlIGVsZW1lbnQgdG8gb3VyIG92ZXJhbGwgcGxvdCB0aGF0IHdlIHdpbGwgYWRkIHRvIGEgY29tYmluZWQgcGxvdCBvZiBvdXIgZXhpc3RpbmcgcGxvdHMgd2UgY2FuIHVzZSBgZ2dkcmF3KClgIHRvIHN0YXJ0IGFuZCB0aGVuIHRoZSBgZHJhd19sYWJlbCgpYCBmdW5jdGlvbiB0byBhZGQgdGV4dC4KCmBgYHtyfQp0aXRsZV9wbG90cyA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICAiU2VsZi1SZXBvcnRlZCBEZXByZXNzaW9uIEFtb25nIEFtZXJpY2FuIFlvdXRocyIsCiAgICBmb250ZmFjZSA9ICdib2xkJywKICAgIHNpemU9MTgsCiAgICB4ID0gMCwKICAgIGhqdXN0ID0gLTAuMDEKICApICsKICB0aGVtZSgKICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDAsIDAsIDAsIDAuNSkKICApCmBgYAoKV2UgY2FuIGFsc28gbWFrZSBhIHN1YnRpdGxlIGluIHRoZSBzYW1lIHdheS4KCmBgYHtyfQoKZm9yd2FyZCA8LSBnZ2RyYXcoKSArIAogIGRyYXdfbGFiZWwoCiAgICAiVGhlIHBlcmNlbnRhZ2Ugb2YgeW91dGhzIGV4cGVyaWVuY2luZyBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGVzIGFuZCByZWNlaXZpbmcgdHJlYXRtZW50XG4gZm9yIGRlcHJlc3Npb24gaGFzIGluY3JlYXNlZCBlc3BlY2lhbGx5IHNpbmNlIDIwMTEiLAogICAgZm9udGZhY2UgPSAnYm9sZCcsCiAgICBzaXplPTE0LAogICAgeCA9IDAsCiAgICBoanVzdCA9IC0wLjAxCiAgKSArCiAgdGhlbWUoCiAgICBwbG90Lm1hcmdpbiA9IG1hcmdpbigwLCAwLCAwLCAwKQogICkKCgoKYGBgCgpOb3cgd2Ugd2lsbCBtb2RpZnkgc29tZSBvZiBvdXIgZXhpc3RpbmcgcGxvdHMgdXNpbmcgdGhlIGB0aGVtZSgpYCBmdW5jdGlvbiBhcyB3ZSBkaWQgYmVmb3JlIHRvIHJlbW92ZSB0aGUgeC1heGlzIHRpdGxlLCB0byBjaGFuZ2UgdGhlIGNvbG9yIG9mIHRoZSBheGlzIHRleHQgYW5kIHRoZSB0aXRsZSBzaXplIGFuZCBjb2xvciwgYXMgd2VsbCBhcyBjaGFuZ2UgdGhlIHRpdGxlcyBvZiB0aGUgcGxvdHMuIAoKYGBge3J9CgpNREVfdG90YWxfZm9yX21wIDwtTURFX3RvdGFsICsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiksCiAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICBheGlzLnRleHQgPSBlbGVtZW50X3RleHQoY29sb3IgPSAiYmxhY2siKSkgKwogIGxhYnModGl0bGUgPSAiVGhlIHBlcmNlbnQgb2YgeW91dGhzIHdobyByZXBvcnRlZCBoYXZpbmcgYVxubWFqb3IgZGVwcmVzc2l2ZSBlcGlzb2RlIikgCgp0cmVhdF9mb3JfbXAgPC0gVHJlYXRfdG90YWwgKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSwKICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgIGF4aXMudGV4dCA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJibGFjayIpKSArCiAgbGFicyh0aXRsZSA9ICJUaGUgcGVyY2VudCBvZiB5b3V0aHMgd2hvIHJlcG9ydGVkIHJlY2VpdmluZ1xudHJlYXRtZW50IGZvciBkZXByZXNzaW9uIiwgc3VidGl0bGUgPSAiIiwgeCA9ICIiKQoKCk1ERV9hZ2Vfc2V4X2Zvcl9tcCA8LSBNREVfYWdlX3NleCArCiAgdGhlbWUocGxvdC50aXRsZT0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sb3IgPSAiYmxhY2siKSwKICAgICAgICBwbG90LnN1YnRpdGxlID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSkgKwogIGxhYnModGl0bGUgPSAiRmVtYWxlcyBhbmQgb2xkZXIgeW91dGhzIGhhdmUgaGlnaGVzdCByYXRlcyBhbmQgc2hvd1xudGhlIHN0ZWVwZXN0IGluY3JlYXNlIikgCgpgYGAKCkZvciB0aGlzIGxhc3QgcGxvdCB3ZSBhbHNvIHdhbnQgdG8gZ2V0IHRoZSBsZWdlbmQgYW5kIHNhdmUgaXQgYXMgYSBzZXBhcmF0ZSBvYmplY3Qgc28gdGhhdCB3ZSBjYW4gYWRkIGl0IHRvIG91ciBwbG90IGdyaWQgaW4gYSB3YXkgdGhhdCBkb2Vzbid0IHNocmluayB0aGUgc2l6ZSBvZiBvdXIgcGxvdCB0byBhY2NvbW1vZGF0ZSB0aGUgbGVnZW5kLiBXZSBjYW4gdXNlIHRoZSBgZ2V0X2xlZ2VuZCgpYCBmdW5jdGlvbiBvZiB0aGUgYGNvd3Bsb3RgIHBhY2thZ2UgdG8gZG8gdGhpcy4gSG93ZXZlciwgYmVmb3JlaGFuZCwgd2UgYWxzbyB3YW50IHRvIGNoYW5nZSB0aGUgd2F5IHRoZSBsZWdlbmQgaXMgZGlzcGxheWVkLiBXZSBjYW4gdXNlIHRoZSBgZ3VpZGVzKClgIGZ1bmN0aW9uIG9mIHRoZSBgZ2dwbG90MmAgcGFja2FnZSB0byBtb2RpZnkgdGhlIGxlZ2VuZCB0byBzcGVjaWZ5IHRoYXQgd2Ugd2FudCB0aGUgbGVnZW5kIHRvIGJlIGRpc3BsYXllZCBpbiAyIHJvd3MgbGlrZSBzbyBgZ3VpZGVzKGd1aWRlX2xlZ2VuZChucm93ID0gMikpYC4KYGBge3J9Ck1ERV9yYWNlX2Zvcl9tcF9sZWcgPC0gTURFX3JhY2UgKwogIHRoZW1lKHBsb3QudGl0bGU9IGVsZW1lbnRfdGV4dChzaXplID0gMTQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yID0gImJsYWNrIiksCiAgICAgICAgcGxvdC5zdWJ0aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIsIAogICAgICAgIGxlZ2VuZC50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBsZWdlbmQudGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gMTQpKSArCiAgbGFicyh0aXRsZSA9ICJBbGwgcmFjaWFsL2V0aG5pYyBncm91cHMgc2hvdyBzaW1pbGFyXG5pbmNyZWFzZXMgc2luY2UgMjAxMSIpICsKICBndWlkZXMoZ3VpZGVfbGVnZW5kKG5yb3cgPSAyKSkKCmxlZ2VuZCA8LWdldF9sZWdlbmQoTURFX3JhY2VfZm9yX21wX2xlZykKCmBgYAoKTm93IHdlIHdpbGwgcmVtb3ZlIHRoZSBsZWdlbmQgZm9yIHRoaXMgcGxvdDoKYGBge3J9Ck1ERV9yYWNlX2Zvcl9tcCA8LU1ERV9yYWNlX2Zvcl9tcF9sZWcgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKCmBgYAoKT0ssIG5vdyB3ZSBhcmUgcmVhZHkgdG8gc3RhcnQgcHV0dGluZyBvdXIgcGxvdHMgdG9nZXRoZXIgdXNpbmcgdGhlIGBwbG90X2dyaWQoKWAgZnVuY3Rpb24gb2YgdGhlIGBjb3dwbG90YCBwYWNrYWdlLiAKCkl0IGlzIGhlbHBmdWwgdG8gZmlyc3QgbWFrZSByb3dzIGJ5IGNvbWJpbmluZyB0aGUgcGxvdHMgdGhhdCB3ZSB3YW50IHRvIGJlIGRpc3BsYXllZCBuZXh0IHRvIGVhY2ggb3RoZXIgYW5kIHRoZW4gY29tYmluaW5nIHRoZXNlIHdpdGggdGhlIHRpdGxlIGFuZCBzdWJ0aXRsZSwgY2FsbGVkIGBmb3J3YXJkYC4gCgpXZSBjYW4gdXNlIHRoZSBgcmVsX3dpZHRoc2AgYXJndW1lbnQgdG8gbW9kaWZ5IGhvdyB3aWRlIGVhY2ggcGxvdCBpcyBkaXNwbGF5ZWQuCgpgYGB7cn0Kcm93XzEgPC0gcGxvdF9ncmlkKE1ERV90b3RhbF9mb3JfbXAsCiAgICAgICAgICAgICAgICAgICB0cmVhdF9mb3JfbXAsCiAgICAgICAgICAgICAgICAgICBucm93ID0gMSkKcm93XzIgPC0gcGxvdF9ncmlkKE1ERV9hZ2Vfc2V4X2Zvcl9tcCwKICAgICAgICAgICAgICAgICAgIE1ERV9yYWNlX2Zvcl9tcCwKICAgICAgICAgICAgICAgICAgIG5yb3cgPSAxLCByZWxfd2lkdGhzID0gYygxLjIsIDAuOCkpCgpgYGAKCgpOb3cgd2UgY2FuIGNvbWJpbmUgZXZlcnl0aGluZyB0b2dldGhlciB1c2luZyBgcGxvdF9ncmlkKClgIHlldCBhZ2Fpbi4gTm93IHRoYXQgd2UgaGF2ZSByb3dzLCB3ZSBjYW4gY29tYmluZSBldmVyeXRoaW5nIGFzIGEgc2luZ2xlIGNvbHVtbiBhbmQgZWFzaWx5IG1vZGlmeSB0aGUgcmVsYXRpdmUgaGVpZ2h0cyB1c2luZyB0aGUgYHJlbF9oZWlnaHRzKClgIGZ1bmN0aW9uIHNvIHRoYXQgb3VyIHRpdGxlLCBzdWJ0aXRsZSBhbmQgbGVnZW5kIGFyZSBhbGwgcmVsYXRpdmUgc2hvcnQgcmVsYXRpdmUgdG8gdGhlIHBsb3RzLiBXZSB3aWxsIG1ha2UgdGhlIGZpcnN0IHJvdyBoYWxmIHRoZSBoZWlnaHQgb2YgdGhlIHNlY29uZCByb3cuIAoKRmluYWxseSwgd2Ugd2lsbCB1c2UgdGhlIGBwbmcoKWAgZnVuY3Rpb24gb2YgdGhlIGBnckRldmljZXNgIHBhY2thZ2Ugd2hpY2ggaXMgYXV0b21hdGljYWxseSBsb2FkZWQgaW4gUlN0dWRpbyBzZXNzaW9ucyB0byBzYXZlIHRoZSBwbG90LiBXZSB3aWxsIHVzZSB0aGUgYGhlcmUoKWAgZnVuY3Rpb24gb2YgdGhlIGBoZXJlYCBwYWNrYWdlLCB0byBzcGVjaWZ5IHRoYXQgd2Ugd2FudCB0byBzYXZlIGl0IGluIHRoZSBgaW1nYCBkaXJlY3RvcnkgYW5kIGNhbGwgaXQgYG1haW5wbG90LnBuZ2AuIFdlIGNhbiBhbHNvIHVzZSB0aGlzIGZ1bmN0aW9uIHRvIHNwZWNpZnkgdGhlIHJlc29sdXRpb24gd2l0aCBgcmVzYCBhbmQgaW4gZG9pbmcgc28sIHdlIG5lZWQgdG8gc2F2ZSB0aGUgaW1hZ2Ugd2l0aCBzaXplIHNwZWNpZmljYXRpb25zIHRvIG1ha2UgaXQgbGFyZ2VyLiAKCmBgYHtyLCBldmFsID0gRkFMU0V9CnBuZyhmaWxlbmFtZSA9IGhlcmU6OmhlcmUoImltZyIsICJtYWlucGxvdC5wbmciKSwgCiAgICAgICAgIHJlcyA9IDMwMCwgd2lkdGggPSAxMCwgaGVpZ2h0ID0gMTAsIHVuaXRzID0gImluIikKcGxvdF9ncmlkKHRpdGxlX3Bsb3RzLCAKICAgICAgICAgIGZvcndhcmQsCiAgICAgICAgICByb3dfMSwKICAgICAgICAgIHJvd18yLAogICAgICAgICAgbGVnZW5kLAogICAgICAgICAgbmNvbCA9IDEsIAogICAgICAgICAgcmVsX2hlaWdodHMgPSBjKDAuMSwwLjEsLjUsIDEsIDAuMikpCgpkZXYub2ZmKCkKYGBgCgpUaGUgYGRldi5vZmYoKWAgZnVuY3Rpb24gaXMgbmVjZXNzYXJ5IHRvIGNsb3NlIHRoZSBncmFwaGljcyBkZXZpY2UuIFRoaXMgaXMgZ29vZCBwcmFjdGljZSB0byBhbGxvdyB5b3UgdG8gY3JlYXRlIGFub3RoZXIgcGxvdCBhZ2FpbiBsYXRlci4KCmBgYHtyLGVjaG8gPSBGQUxTRX0Ka25pdHI6OmluY2x1ZGVfZ3JhcGhpY3MoaGVyZTo6aGVyZSgiaW1nIiwgIm1haW5wbG90LnBuZyIpKQpgYGAKCmF2b2NhZG86IEkgd2FudCB0byBhZGQgc29tZXRoaW5nIGFib3V0IHNlbGYtcmVwb3J0aW5nIGJpYXMgdG8gdGhlICBvYmplY3RpdmVzCgojIyMgU3lub3BzaXMKCkluIHRoaXMgY2FzZSBzdHVkeSB3ZSBldmFsdWF0ZWQgc2VsZi1yZXBvcnRlZCBtZWFzdXJlcyBvZiBkZXByZXNzaW9uIHN5bXB0b21zIGFtb25nIHlvdXRocyBhZ2UgMTItMTcgaW4gdGhlIFVuaXRlZCBTdGF0ZXMsIGFzIHdlbGwgYXMgdGhlIHJhdGUgb2YgeW91dGhzIHJlY2VpdmluZyB0cmVhdG1lbnQgZm9yIGRlcHJlc3Npb24uIFdlIGxlYXJuZWQgaG93IHRvIHNjcmFwZSBkYXRhIGRpcmVjdGx5IGZyb20gdGhlIHdlYiB1c2luZyB0aGUgYHJ2ZXN0YCBwYWNrYWdlIGFuZCB3ZSBsZWFybmVkIGhvdyB0byBwZXJmb3JtIGFuZCBpbnRlcnByZXQgYSBjaGktc3F1YXJlIHRlc3QgdXNpbmcgdGhlIGBjaGlzcS50ZXN0KClgIGZ1bmN0aW9uIG9mIHRoZSBgc3RhdHNgIHBhY2thZ2UuCgpCeSBhbmFseXppbmcgYW5kIHBsb3R0aW5nIG91ciBkYXRhLCBpdCBpcyBjbGVhciB0aGF0IGRlcHJlc3Npb24gcmF0ZXMgYXBwZWFyIHRvIGJlIGluY3JlYXNpbmcsIHBhcnRpY3VsYXJseSBzaW5jZSAyMDExLiBIb3dldmVyLCBpdCBpcyBwb3NzaWJsZSB0aGF0IHJlc3BvbmRlbnRzIGhhZCBzaW1pbGFyIHJhdGVzIGluIHByZXZpb3VzIHllYXJzLCBidXQgbm93IGZlZWwgbGVzcyBzdGlnbWEgYWJvdXQgcmVzcG9uZGluZyBhYm91dCBkZXByZXNzaW9uIHN5bXB0b21zIHdoZW4gZmlsbGluZyBvdXQgdGhlIHN1cnZleS4gVGhlIHN1cnZleSBoYXMgYWx3YXlzIGJlZW4gYW5vbnltb3VzLCBidXQgW3JlcG9ydGluZyBiaWFzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9TZWxmLXJlcG9ydF9zdHVkeSM6fjp0ZXh0PVNlbGYlMkRyZXBvcnQlMjBzdHVkaWVzJTIwYXJlJTIwaW5oZXJlbnRseSxhbnN3ZXJzJTIwd2lsbCUyMGJlJTIwbW9yZSUyMHBvc2l0aXZlLil7dGFyZ2V0PSJfYmxhbmsifSBjYW4gc29tZXRpbWVzIGNhdXNlIGluZGl2aWR1YWxzIHRvIGV4YWdnZXJhdGUgb3IgbWluaW1pemUgdGhlaXIgc3ltcHRvbXMgYmVjYXVzZSBvZiB3aGF0IHRoZXkgdGhpbmsgcmVzZWFyY2hlcnMgd2FudCB0aGVpciByZXNwb25zZSB0byBiZSBvciBvdXQgb2Ygc2hhbWUgb3IgZW1iYXJyYXNzbWVudCwgYW1vbmcgb3RoZXIgcmVhc29ucy4gSG93ZXZlciwgdGhlIGRhdGEgc3VnZ2VzdHMgdGhhdCB5b3V0aHMgbWF5IGJlIGV4cGVyaWVuY2luZyBtb3JlIHN5bXB0b21zIG9mIGRlcHJlc3Npb24gYW5kIHRoYXQgdGhlIHJhdGUgb2YgaW5jcmVhc2UgaXMgcXVpdGUgaGlnaC4gTm93IG5lYXJseSBhIHF1YXJ0ZXIgb2YgYWxsIGluZGl2aWR1YWxzIHRoYXQgd2VyZSBmZW1hbGUgYW5kIG9mIGFnZSAxMi0xNyByZXBvcnRlZCBleHBlcmllbmNpbmcgc3ltcHRvbXMgb2YgZGVwcmVzc2lvbi4gVGhpcyB3YXJyYW50cyBmdXJ0aGVyIGludmVzdGlnYXRpb24gdG8gc2VlIGlmIHRoaXMgaXMgYSBwcm9kdWN0IG9mIG1vcmUgcmVwb3J0aW5nIG9yIGlmIGluZGVlZCBBbWVyaWNhbiBmZW1hbGVzIGFyZSB0cnVseSBtb3JlIGRlcHJlc3NlZC4gRnVydGhlcm1vcmUsaWYgdGhleSBhcmUgaW5kZWVkIG1vcmUgZGVwcmVzc2VkLCBpbnZlc3RpZ2F0aW9uIGFib3V0IHdoeSB5b3VuZyBmZW1hbGVzIGFyZSBtb3JlIGRlcHJlc3NlZCBpcyBhbHNvIG9mIGNyaXRpY2FsIGltcG9ydGFuY2UuIE9uZSBpbXBvcnRhbnQgbGltaXRhdGlvbiBpcyB0aGF0IHRoZSBkYXRhIGRvZXMgbm90IGluY2x1ZGUgc3ViZ3JvdXAgaW50ZXJzZWN0aW9ucywgc3VjaCBhcyByYXRlcyBvZiBtYWpvciBkZXByZXNzaXZlIGVwaXNvZGVzIGFtb25nIGZlbWFsZXMgb2YgdmFyaW91cyBldGhuaWMgYmFja2dyb3VuZHMuIENvbnNpZGVyaW5nIHRoZSB2ZXJ5IHN0ZWVwIGluY3JlYXNlIGluIGZlbWFsZXMsIHRoaXMgd2FycmFudHMgZnVydGhlciBpbnZlc3RpZ2F0aW9uIGFib3V0IHdoaWNoIGZlbWFsZXMgYXJlIHBhcnRpY3VsYXJseSB2dWxuZXJhYmxlIGFuZCB3aHkuIAoKCiMjICoqSG9tZXdvcmsqKgoqKiogCgpBc2sgc3R1ZGVudHMgdG8gc2NyYXBlIHRhYmxlcyAxMS41QSBhbmQgMTEuNUIgZnJvbSB0aGUgd2Vic2l0ZSB3aGljaCBjb250YWluIGRhdGEgYWJvdXQgdGhlIHJlY2VpcHQgb2YgdHJlYXRtZW50IGFtb25nIHlvdXRocyB3aG8gcmVwb3J0ZWQgaGF2aW5nIGEgc2V2ZXJlIGVwaXNvZGUuIEFzayBzdHVkZW50cyB0byBjcmVhdGUgcGxvdHMgYW5kIHBlcmZvcm0gY2hpLXNxdWFyZSB0ZXN0cyB0byBldmFsdWF0ZSBob3cgZ3JvdXBzIGNvbXBhcmUgb3ZlciB0aW1lLgoKCiMjICoqQWRkaXRpb25hbCBJbmZvcm1hdGlvbioqCioqKgoKIyMjIEhlbHBmdWwgTGlua3MKCltSU3R1ZGlvXShodHRwczovL3JzdHVkaW8uY29tL3Byb2R1Y3RzL3JzdHVkaW8vZmVhdHVyZXMvKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0NoZWF0c2hlZXQgb24gUlN0dWlkbyBJREVdKGh0dHBzOi8vZ2l0aHViLmNvbS9yc3R1ZGlvL2NoZWF0c2hlZXRzL3Jhdy9tYXN0ZXIvcnN0dWRpby1pZGUucGRmKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW090aGVyIFJTdHVkaW8gY2hlYXRzaGVldHNdKGh0dHBzOi8vcnN0dWRpby5jb20vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLyl7dGFyZ2V0PSJfYmxhbmsifSAgIApbVGlkeXZlcnNlXShodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgIApbU2VsZWN0aW9uIGJpYXNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NlbGVjdGlvbl9iaWFzP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1NhbXBsaW5nIG1ldGhvZHNdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXBsaW5nXyhzdGF0aXN0aWNzKT9vbGRmb3JtYXQ9dHJ1ZSl7dGFyZ2V0PSJfYmxhbmsifSAgIApbU2FtcGxpbmcgZnJhbWVdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1NhbXBsaW5nX2ZyYW1lP29sZGZvcm1hdD10cnVlKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW0RTTSA1XShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9EU00tNSl7dGFyZ2V0PSJfYmxhbmsifTwvc3VtbWFyeT4gICAgCltOYXRpb25hbCBTdXJ2ZXkgb24gRHJ1ZyBVc2UgYW5kIEhlYWx0aCAoTlNEVUgpXShodHRwczovL25zZHVod2ViLnJ0aS5vcmcvcmVzcHdlYi9ob21lcGFnZS5jZm0pe3RhcmdldD0iX2JsYW5rIn0gICAKW1N1YnN0YW5jZSBBYnVzZSBhbmQgTWVudGFsIEhlYWx0aCBTZXJ2aWNlcyBBZG1pbmlzdHJhdGlvbiAoU0FNSFNBKV0oaHR0cHM6Ly93d3cuc2FtaHNhLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0gICAKW1UuUy4gRGVwYXJ0bWVudCBvZiBIZWFsdGggYW5kIEh1bWFuIFNlcnZpY2VzIChESEhTKV0oaHR0cHM6Ly93d3cuaGhzLmdvdi8pe3RhcmdldD0iX2JsYW5rIn0gICAKW05TRFVIIFN1cnZleSBSZXN1bHRzIFdlYnNpdGVdKGh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRUYWJzU2VjdDExcGUyMDE4Lmh0bSl7dGFyZ2V0PSJfYmxhbmsifSAod2hlcmUgd2UgZ290IHRoZSBkYXRhIGZvciB0aGlzIGNhc2Ugc3R1ZHkpICAgIApbRGV0YWlscyBhYm91dCB0aGUgU3VydmV5XShodHRwczovL25zZHVod2ViLnJ0aS5vcmcvcmVzcHdlYi9hYm91dF9uc2R1aC5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW1JlcG9ydCBhYm91dCB0aGUgMjAxOCBOU0RVSCBTdXJ2ZXldKGh0dHBzOi8vd3d3LnNhbWhzYS5nb3YvZGF0YS9zaXRlcy9kZWZhdWx0L2ZpbGVzL2NiaHNxLXJlcG9ydHMvTlNEVUhEZXRhaWxlZFRhYnMyMDE4UjIvTlNEVUhEZXRhaWxlZFRhYnMyMDE4LnBkZil7dGFyZ2V0PSJfYmxhbmsifSAgCltXZWIgc2NyYXBpbmddKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1dlYl9zY3JhcGluZz9vbGRmb3JtYXQ9dHJ1ZSl7dGFyZ2V0PSJfYmxhbmsifSAgCltTZWxlY3RvcmdhZGdldCBUb29sXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvcnZlc3QvdmlnbmV0dGVzL3NlbGVjdG9yZ2FkZ2V0Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIApTZWUgdGhpcyBbYmxvZyBwb3N0XShodHRwOi8vcmVzZWFyY2gubGliZC5vcmcvcnN0YXRzY2x1Yi9wb3N0L2ludHJvZHVjdGlvbi10by1zY3JhcGluZy1hbmQtd3JhbmdpbmctdGFibGVzLWZyb20tcmVzZWFyY2gtYXJ0aWNsZXMvIy5Ydzg3OFpOS2hRSil7dGFyZ2V0PSJfYmxhbmsifSwgdGhpcyBbYmxvZyBwb3N0XShodHRwOi8vYmxvZy5jb3J5bmlzc2VuLmNvbS8yMDE1LzAxL3VzaW5nLXJ2ZXN0LXRvLXNjcmFwZS1odG1sLXRhYmxlLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0sIGFuZCB0aGlzIFt2aWduZXR0ZV0oaHR0cHM6Ly9yc3R1ZGlvLXB1YnMtc3RhdGljLnMzLmFtYXpvbmF3cy5jb20vMjY2NDMwX2YzZmQ0NjYwYjI3NDQ3NTFhYjE0NGFhMTMwNzY4YTA2Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gZm9yIG1vcmUgaW5mb3JtYXRpb24gYWJvdXQgd2ViIHNjcmFwaW5nICAKW0NTUyBzZWxlY3RvcnMgdHV0b3JpYWxdKGh0dHA6Ly9mbHVrZW91dC5naXRodWIuaW8vIyl7dGFyZ2V0PSJfYmxhbmsifSAoYW5kIHRoZSBbYW5zd2Vyc10oaHR0cHM6Ly9naXN0LmdpdGh1Yi5jb20vY2hyaXNtYW4vZmNiMGE4ODQ1OWNkOTgyMzlkYmU2ZDJkMjAwYjAyZDEpe3RhcmdldD0iX2JsYW5rIn0pICAgICAKW1BpcGluZyBpbiBSXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvbWFncml0dHIvdmlnbmV0dGVzL21hZ3JpdHRyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gICAKW1dyaXRpbmcgZnVuY3Rpb25zXShodHRwczovL3I0ZHMuaGFkLmNvLm56L2Z1bmN0aW9ucy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9CkFsc28gc2VlIFt0aGlzIGNhc2Ugc3R1ZHldKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9vY3MtYmxvb21iZXJnLXZhcGluZy1jYXNlLXN0dWR5Lyl7dGFyZ2V0PSJfYmxhbmsifSAgZm9yIG1vcmUgaW5mb3JtYXRpb24gb24gd3JpdGluZyBmdW5jdGlvbnMuICAgCltTdHJpbmcgbWFuaXB1bGF0aW9uIGNoZWF0c2hlZXRdKGh0dHBzOi8vcnN0dWRpby5jb20vcmVzb3VyY2VzL2NoZWF0c2hlZXRzLyl7dGFyZ2V0PSJfYmxhbmsifSAgCltUYWJsZSBmb3JtYXRzXShodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9XaWRlX2FuZF9uYXJyb3dfZGF0YSl7dGFyZ2V0PSJfYmxhbmsifQpbUGVhcnNvbidzIGNoaS1zcXVhcmVkIHRlc3RdKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL1BlYXJzb24lMjdzX2NoaS1zcXVhcmVkX3Rlc3QjOn46dGV4dD1QZWFyc29uJ3MlMjBjaGklMkRzcXVhcmVkJTIwdGVzdCUyMGlzLGRpZmZlcnMlMjBmcm9tJTIwYSUyMHRoZW9yZXRpY2FsJTIwZGlzdHJpYnV0aW9uLil7dGFyZ2V0PSJfYmxhbmsifSAgCltjb250aW5nZW5jeSB0YWJsZV0oaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ29udGluZ2VuY3lfdGFibGUpe3RhcmdldD0iX2JsYW5rIn0gIApbQ2hpLXNxdWFyZSBkaXN0cmlidXRpb25dKGh0dHBzOi8vZW4ud2lraXBlZGlhLm9yZy93aWtpL0NoaS1zcXVhcmVkX3Rlc3QjL21lZGlhL0ZpbGU6Q2hpLXNxdWFyZV9kaXN0cmlidXRpb25DREYtRW5nbGlzaC5wbmcpe3RhcmdldD0iX2JsYW5rIn0gIApbY2hpLXNxdWFyZSBkaXN0cmlidXRpb24gYXBwbGV0XShodHRwOi8vaG9tZXBhZ2UuZGl2bXMudWlvd2EuZWR1L35tYm9nbmFyL2FwcGxldHMvY2hpc3EuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgClNlZSBoZXJlIGZvciBhIG1vcmUgdGhvcm91Z2ggZXhwbGFuYXRpb24gb2YgdGhlIFtjaGktc3F1YXJlIHRlc3RdKGh0dHBzOi8vd3d3LmxpbmcudXBlbm4uZWR1L35jbGlnaHQvY2hpc3F1YXJlZC5odG0pe3RhcmdldD0iX2JsYW5rIn0gICAKW2BnZ3Bsb3QyYCBwYWNrYWdlXShodHRwOi8vZ2dwbG90Mi50aWR5dmVyc2Uub3JnKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIApQbGVhc2Ugc2VlIFt0aGlzIGNhc2Ugc3R1ZHldKGh0dHBzOi8vb3BlbmNhc2VzdHVkaWVzLmdpdGh1Yi5pby9vY3MtYnAtY28yLWVtaXNzaW9ucy8pe3RhcmdldD0iX2JsYW5rIn0gIGZvciBtb3JlIGRldGFpbHMgb24gdXNpbmcgYGdncGxvdDJgLiAKW2dyYW1tYXIgb2YgZ3JhcGhpY3NdKGh0dHA6Ly92aXRhLmhhZC5jby5uei9wYXBlcnMvbGF5ZXJlZC1ncmFtbWFyLmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIApbYGdncGxvdDJgIHRoZW1lc10oaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvcmVmZXJlbmNlL2dndGhlbWUuaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgIApbYGRpcmVjdGxhYmVsc2AgcGFja2FnZSBtZXRob2RzXShodHRwOi8vZGlyZWN0bGFiZWxzLnItZm9yZ2Uuci1wcm9qZWN0Lm9yZy9kb2NzL2luZGV4Lmh0bWwpe3RhcmdldD0iX2JsYW5rIn0gIApbVmlyaWRpcyBwYWxldHRlIGZvciBjb2xvcmJsaW5kIGZyaWVuZGx5IHBsb3RzXShodHRwczovL2NyYW4uci1wcm9qZWN0Lm9yZy93ZWIvcGFja2FnZXMvdmlyaWRpcy92aWduZXR0ZXMvaW50cm8tdG8tdmlyaWRpcy5odG1sKXt0YXJnZXQ9Il9ibGFuayJ9ICAKW01vdGl2YXRpbmcgYXJ0aWNsZSBmb3IgdGhpcyBjYXNlIHN0dWR5IGFib3V0IGRlcHJlc3Npb24gcmF0ZXNdKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMzA4Njk5MjcvKXt0YXJnZXQ9Il9ibGFuayJ9IChBY2Nlc3MgaXMgcG9zc2libGUgZm9yIHRob3NlIGF0IEhvcGtpbnMgYnkgdXNpbmcgdGhlaXIgZW1haWwgYWRkcmVzcykgICAgCgpbTW90aXZhdGluZyBhcnRpY2xlIGFib3V0IHRoZSByYXRlIG9mIHlvdXRocyBzZWVraW5nIG1lbnRhbCBoZWFsdGggc2VydmljZXNdKGh0dHBzOi8vcHVibWVkLm5jYmkubmxtLm5paC5nb3YvMjQyODUzODIvKXt0YXJnZXQ9Il9ibGFuayJ9ICAgIAoKW0Nyb3NzLWN1bHR1cmFsIHJldmlldyBhcnRpY2xlIGFib3V0IHBvc3NpYmxlIGNhdXNlcyBmb3IgaW5jcmVhc2VkIGRlcHJlc3Npb25dKGh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzMzMzAxNjEvKXt0YXJnZXQ9Il9ibGFuayJ9CgpbUmV2aWV3IGFydGljbGUgYWJvdXQgc29jaWFsIG1lZGlhIGFuZCBkZXByZXNzaW9uXShodHRwczovL2NoaWxkbWluZC5vcmcvYXJ0aWNsZS9pcy1zb2NpYWwtbWVkaWEtdXNlLWNhdXNpbmctZGVwcmVzc2lvbi8pe3RhcmdldD0iX2JsYW5rIn0KCgo8dT4qKlBhY2thZ2VzIHVzZWQgaW4gdGhpcyBjYXNlIHN0dWR5OioqIDwvdT4KClBhY2thZ2UgICB8IFVzZSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAKLS0tLS0tLS0tLSB8LS0tLS0tLS0tLS0tLQpbaGVyZV0oaHR0cHM6Ly9naXRodWIuY29tL2plbm55YmMvaGVyZV9oZXJlKXt0YXJnZXQ9Il9ibGFuayJ9ICAgICAgIHwgdG8gZWFzaWx5IGxvYWQgYW5kIHNhdmUgZGF0YSAgCltydmVzdF0oaHR0cHM6Ly9naXRodWIuY29tL3RpZHl2ZXJzZS9ydmVzdCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gc2NyYXBlIHdlYiBwYWdlcyAgCltkcGx5cl0oaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gc2NyYXBlIHdlYiBwYWdlcyAgClttYWdyaXR0cl0oaHR0cHM6Ly9tYWdyaXR0ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gc2NyYXBlIHdlYiBwYWdlcyAgCltzdHJpbmdyXShodHRwczovL3N0cmluZ3IudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIG1hbmlwdWxhdGUgc3RyaW5ncyAgClt0aWR5cl0oaHR0cHM6Ly90aWR5ci50aWR5dmVyc2Uub3JnLyl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gY2hhbmdlIHRoZSBzaGFwZSBvciBmb3JtYXQgb2YgdGliYmxlcyB0byB3aWRlIGFuZCBsb25nICAKW3RpYmJsZV0oaHR0cHM6Ly90aWJibGUudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGNyZWF0ZSB0aWJibGVzIGFuZCBjb252ZXJ0IGEgY29sdW1uIHRvIHJvdyBuYW1lcyAgCltnZ3Bsb3QyXShodHRwczovL2dncGxvdDIudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIGNyZWF0ZSBwbG90cyAgCltkaXJlY3RsYWJlbHNdKGh0dHA6Ly9kaXJlY3RsYWJlbHMuci1mb3JnZS5yLXByb2plY3Qub3JnL2RvY3MvaW5kZXguaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gYWRkIGxhYmVscyBkaXJlY3RseSB0byBsaW5lcyBpbiBwbG90cyAgCltmb3JjYXRzXShodHRwczovL2ZvcmNhdHMudGlkeXZlcnNlLm9yZy8pe3RhcmdldD0iX2JsYW5rIn0gICAgICB8IHRvIHJlb3JkZXIgZmFjdG9yIGZvciBwbG90ICAKW2Nvd3Bsb3RdKGh0dHBzOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9jb3dwbG90L3ZpZ25ldHRlcy9pbnRyb2R1Y3Rpb24uaHRtbCl7dGFyZ2V0PSJfYmxhbmsifSAgICAgIHwgdG8gY29tYmluZSBwbG90cyB0b2dldGhlciAgCgojIyMjIHsuZW1waGFzaXNfYmxvY2t9CklmIHlvdSBhcmUgaW4gY3Jpc2lzIGFuZCBuZWVkIGhlbHAsIGNhbGwgdGhpcyB0b2xsLWZyZWUgbnVtYmVyIGZvciB0aGUgKipOYXRpb25hbCBTdWljaWRlIFByZXZlbnRpb24gTGlmZWxpbmUgKE5TUEwpKiosIGF2YWlsYWJsZSAyNCBob3VycyBhIGRheSwgZXZlcnkgZGF5OiAqKjEtODAwLTI3My1UQUxLICg4MjU1KSoqLiBUaGUgc2VydmljZSBpcyBhdmFpbGFibGUgdG8gZXZlcnlvbmUuIFRoZSBkZWFmIGFuZCBoYXJkIG9mIGhlYXJpbmcgY2FuIGNvbnRhY3QgdGhlIExpZmVsaW5lIHZpYSBUVFkgYXQgMS04MDAtNzk5LTQ4ODkuIEFsbCBjYWxscyBhcmUgY29uZmlkZW50aWFsLiBZb3UgY2FuIGFsc28gdmlzaXQgdGhlIExpZmVsaW5l4oCZcyB3ZWJzaXRlIGF0IFt3d3cuc3VpY2lkZXByZXZlbnRpb25saWZlbGluZS5vcmddKHd3dy5zdWljaWRlcHJldmVudGlvbmxpZmVsaW5lLm9yZyl7dGFyZ2V0PSJfYmxhbmsifS4KClRoZSAqKkNyaXNpcyBUZXh0IExpbmUqKiBpcyBhbm90aGVyIGZyZWUsIGNvbmZpZGVudGlhbCByZXNvdXJjZSBhdmFpbGFibGUgMjQgaG91cnMgYSBkYXksIHNldmVuIGRheXMgYSB3ZWVrLiBUZXh0IOKAnEhPTUXigJ0gdG8gKio3NDE3NDEqKiBhbmQgYSB0cmFpbmVkIGNyaXNpcyBjb3Vuc2Vsb3Igd2lsbCByZXNwb25kIHRvIHlvdSB3aXRoIHN1cHBvcnQgYW5kIGluZm9ybWF0aW9uIG92ZXIgdGV4dCBtZXNzYWdlLiBWaXNpdCBbd3d3LmNyaXNpc3RleHRsaW5lLm9yZ10od3d3LmNyaXNpc3RleHRsaW5lLm9yZyl7dGFyZ2V0PSJfYmxhbmsifS4KCiMjIyMKCkFsc28gc2VlIFtoZXJlXShodHRwczovL3d3dy5taGFuYXRpb25hbC5vcmcvZGVwcmVzc2lvbi10ZWVucy0wKXt0YXJnZXQ9Il9ibGFuayJ9IGZvciBtb3JlIGluZm9ybWF0aW9uIGFib3V0IGhvdyB0byByZWNvZ25pemUgYW5kIGhlbHAgeW91dGhzIGV4cGVyaWVuY2luZyBzeW1wdG9tcyBvZiBkZXByZXNzaW9uCgoKIyMjIEFja25vd2xlZGdlbWVudHMKCldlIHdvdWxkIGxpa2UgdG8gYWNrbm93bGVkZ2UgW1RhbWFyIE1lbmRlbHNvbl0oaHR0cHM6Ly93d3cuamhzcGguZWR1L2ZhY3VsdHkvZGlyZWN0b3J5L3Byb2ZpbGUvMTc3MC90YW1hci1tZW5kZWxzb24pe3RhcmdldD0iX2JsYW5rIn0gZm9yIGFzc2lzdGluZyBpbiBmcmFtaW5nIHRoZSBtYWpvciBkaXJlY3Rpb24gb2YgdGhlIGNhc2Ugc3R1ZHkuCgpXZSB3b3VsZCBhbHNvIGxpa2UgdG8gYWNrbm93bGVkZ2UgdGhlIFtCbG9vbWJlcmcgQW1lcmljYW4gSGVhbHRoIEluaXRpYXRpdmVdKGh0dHBzOi8vYW1lcmljYW5oZWFsdGguamh1LmVkdS8pe3RhcmdldD0iX2JsYW5rIn0gZm9yIGZ1bmRpbmcgdGhpcyB3b3JrLiAKCgoKCg==